一个char类型的变量多线程访问修改是不是不需要加锁互斥呢 赐教 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 一个char类型的变量其实在多线程中无须加锁保护,因为CPU对单个char类型的数据读写本身就是原子性的 是这样的吗?char int bool不都是整形么一般汇编翻译都是 移进寄存器 修改 移出寄存器 这3步吧 如果这样的话 应该加 为什么就原子了呢? 因为CPU对单个char类型的数据读写本身就是原子性的 --------------------------------------------兄弟不要瞎说啊 InterlockedExchange()Interlocked...这系列函数。 可以不+锁,但你要保证你你的程序需要的是一个随机度较高的修改,或者是一个线程修改,其他线程读写,的确如上面的兄弟所说"CPU对单个char类型的数据读写本身就是原子性的"但你必须保证你对这个变量的修改也是原子性的,比如long g_l_Value;//LONG 也可以long chang_value(){ long lmid,lValue; lmid = g_l_Value; //用lmid进行一系列运算,将结果保存在lValue之中 g_l_Value = lValue;//单赋值原子操作 return lValue;}g_l_Value = lValue;这一句对应的汇编代码是MOV EAX, [lValue];MOV [g_l_Value], EAX;是的只有两句,在两句之间也可能会被执行其他的赋值,所以要求你的程序需要的是一个随机度较高的修改.也就是说,当多个chang_value被执行的时候要求的最终结果只要是根据chang_value被执行只前的某一个g_l_Value运算得到的,而不要求按照一定的时间顺序.一定要把lmid = g_l_Value;然后用lmid运算,否则直接用g_l_Value用进行运算,在A线程先后多次对g_l_Value的操作的同时B线程也在同时做类似的操作,结果两个线程交叉影响,用lmid运算就不会有这样的影响.lmid = g_l_Value;g_l_Value = lValue;这两句发生时虽然也会产生交叉影响,但不会影响值的完整性.也就是说,lmid = g_l_Value;不会把g_l_Value被B运算的前一半和C运算的后一半给lmid.同理g_l_Value = lValue;也不会影响g_l_Value的完整.但要注意对于有时序要求的程序着是不可以的,因为最先运行lmid = g_l_Value;的线程,不一定也最先运行g_l_Value = lValue;我个人认为网络上很多人认为凡是"多线程设计就一定要+锁"这种思想是很不全面的,比如我写过一个随机数计算程序,他是多个进程,是的,是进程,我使用了进程数据共享,当然是WIN32下的,没有一个锁,我仍然可以保证不出任何错误,而且可以得到高度随机的数字,我可以保证在至少连续的4096次运算中不会产生两个相同的数据,在实验中,60多万次的运算也没有产生不均衡的数据,这满足了随机要求.当然对于某些多线程的指针操作最好+锁和标记,因为内存空间可能回被DELETE.上面这些是一些经验之谈,希望对LZ有用,有用就给分哦! 一个char类型的变量其实在多线程中无须加锁保护,因为CPU对单个char类型的数据读写本身就是原子性的===============怎么可能呢?为什么对单个char的处理是原子性的呢? 14楼说的不错,MOV EAX, [lValue]; MOV [g_l_Value], EAX; 有可能被打断哦。 你告诉我什么时候会被打断被打断的话MOV [g_l_Value], EAX的值就不是之前计算出的lValue了吗?只要他"是"那么就可以保证MOV [g_l_Value], EAX;一句就可以保证g_l_Value的完整性.不要告诉我一句汇编代码会被分到两个时间片里面执行,连中断也无法打断单一汇编代码的执行,你说你怎么打断???你看明白我说的是什么了吗?你真正做过多线程并发访问的实验和项目吗?知道什么是TSS机制吗? window核心编程里的意思是说要加锁,但它给的是个long类型long g_x = 0;不过char 应该差不多吧。看来还是加吧。也懒得去验证了 Interlockedxxx操作的就是32位系统上的long(32位整数)可见,不管原子不原子,该同步,该加锁还是加了,程序的健壮永远比执行效率重要! #include "stdafx.h"#include <Windows.h>char g_x = 0;DWORD TreadFun1(PVOID pvParam){ g_x++; return 0;}int TreadFun2(PVOID pvParam){ g_x++; return 0;}int _tmain(int argc, _TCHAR* argv[]){ DWORD dwThreadId1 = 0; DWORD dwThreadId2 = 0; HANDLE hThread1 = NULL; HANDLE hThread2 = NULL; hThread1 = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)TreadFun1, NULL, 0, &dwThreadId1); hThread1 = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)TreadFun2, NULL, 0, &dwThreadId1); Sleep(10000); return 0;}windows核心编程上的问题g_x就一定是2吗? 要看你的编译器如何对待++如果是INC就肯定是2,但其他就可能是1,这要看你做什么,如果你为了计算有多少个线程被运行,你就必须+锁,如果只是为了得到一些数据,那就不用了 那么加个volatile 是否可以不加锁呢 从一个长串中获得子串,用vector保存的最优算法 SOCKET广播之观察者模式,大侠们不能解决真的不好睡觉? 带图标菜单的问题 VS2008调试的一个怪现象 我编辑了一个DLL库的程序,也编辑一个测试程序,可是测试程序不好使,请进入帮助解决(编的DLL程序在别的测试程序好使) 高分求救!!!不够另开题给分 VC如何调试带有输入参数的Console程序? 关于《windows程序设计》这本书 是否有必要升级到256M(用笔记本编程)? 请教: 为什么Attach 一个HDC 中的bitmap 就会出问题? 对话框客户区画图未果求解 如何操作activesync
一般汇编翻译都是 移进寄存器 修改 移出寄存器 这3步吧 如果这样的话 应该加 为什么就原子了呢?
--------------------------------------------
兄弟不要瞎说啊 InterlockedExchange()
Interlocked...这系列函数。
但你必须保证你对这个变量的修改也是原子性的,比如
long g_l_Value;//LONG 也可以long chang_value()
{
long lmid,lValue; lmid = g_l_Value; //用lmid进行一系列运算,将结果保存在lValue之中 g_l_Value = lValue;//单赋值原子操作
return lValue;
}g_l_Value = lValue;
这一句对应的汇编代码是MOV EAX, [lValue];
MOV [g_l_Value], EAX;
是的只有两句,在两句之间也可能会被执行其他的赋值,所以要求你的程序需要的是一个随机度较高的修改.
也就是说,当多个chang_value被执行的时候要求的最终结果只要是根据chang_value被执行只前的某一个g_l_Value运算得到的,而不要求按照一定的时间顺序.
一定要把lmid = g_l_Value;然后用lmid运算,否则直接用g_l_Value用进行运算,在A线程先后多次对g_l_Value的操作的同时B线程也在同时做类似的操作,结果两个线程交叉影响,用lmid运算就不会有这样的影响.
lmid = g_l_Value;
g_l_Value = lValue;
这两句发生时虽然也会产生交叉影响,但不会影响值的完整性.也就是说,lmid = g_l_Value;不会把g_l_Value被B运算的前一半和C运算的后一半给lmid.
同理g_l_Value = lValue;也不会影响g_l_Value的完整.
但要注意对于有时序要求的程序着是不可以的,因为最先运行lmid = g_l_Value;的线程,不一定也最先运行g_l_Value = lValue;
我个人认为网络上很多人认为凡是"多线程设计就一定要+锁"这种思想是很不全面的,比如我写过一个随机数计算程序,他是多个进程,是的,是进程,我使用了进程数据共享,当然是WIN32下的,没有一个锁,我仍然可以保证不出任何错误,而且可以得到高度随机的数字,我可以保证在至少连续的4096次运算中不会产生两个相同的数据,在实验中,60多万次的运算也没有产生不均衡的数据,这满足了随机要求.
当然对于某些多线程的指针操作最好+锁和标记,因为内存空间可能回被DELETE.上面这些是一些经验之谈,希望对LZ有用,有用就给分哦!
===============
怎么可能呢?为什么对单个char的处理是原子性的呢?
MOV [g_l_Value], EAX; 有可能被打断哦。
被打断的话MOV [g_l_Value], EAX的值就不是之前计算出的lValue了吗?只要他"是"那么就可以保证
MOV [g_l_Value], EAX;一句就可以保证g_l_Value的完整性.不要告诉我一句汇编代码会被分到两个时间片里面执行,
连中断也无法打断单一汇编代码的执行,你说你怎么打断???
你看明白我说的是什么了吗?
你真正做过多线程并发访问的实验和项目吗?知道什么是TSS机制吗?
但它给的是个long类型
long g_x = 0;不过char 应该差不多吧。
看来还是加吧。也懒得去验证了
可见,不管原子不原子,该同步,该加锁还是加了,程序的健壮永远比执行效率重要!
#include "stdafx.h"
#include <Windows.h>char g_x = 0;
DWORD TreadFun1(PVOID pvParam)
{
g_x++; return 0;
}int TreadFun2(PVOID pvParam)
{
g_x++; return 0;
}int _tmain(int argc, _TCHAR* argv[])
{
DWORD dwThreadId1 = 0;
DWORD dwThreadId2 = 0;
HANDLE hThread1 = NULL;
HANDLE hThread2 = NULL; hThread1 = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)TreadFun1, NULL, 0, &dwThreadId1);
hThread1 = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)TreadFun2, NULL, 0, &dwThreadId1); Sleep(10000);
return 0;
}windows核心编程上的问题
g_x就一定是2吗?
如果是INC就肯定是2,但其他就可能是1,这要看你做什么,如果你为了计算有多少个线程被运行,你就必须+锁,如果只是为了得到一些数据,那就不用了