难道小弟我对volatile关键字的理解以前都是异常的
难道我对volatile关键字的理解以前都是错误的?
请看代码
理论上输出应该是
实际上却是这样
最奇怪的地方是
thread1 sell ticket = 0
thread1 sell ticket = 0
请高手解惑
------解决方案--------------------
当两个线程同时输出字符串时,会有什么结果?
别以为只有变量需要线程安全,一切“唯一”的东西都需要保证线程安全,包括输出
------解决方案--------------------
volatile 不是用来做临界区的。
而是告知编译器这个符号是易变的。
这样编译器就会假定她使用之间需要检测这个易变性。
比如,需要重新读取,或者不对与之关联的语句进行调整顺序等优化。
我用 volatile 的很大原因就是可以保证因果关系。
------解决方案--------------------
------解决方案--------------------
volatile本来就不是给你拿来做线程同步的。
volatile显式要求lvalue conversion时从对象存储的内存的取值,而非之前取到过的(例如放在cache里的)值。对于一些底层操作,如映射硬件存储,中断处理等场合是必要的。至于多线程,用volatile是有可能解决【一小部分】一致性问题,但会严重阻碍优化。
请看代码
- C/C++ code
volatile int tickets=0; volatile BOOL g_bRun = TRUE; DWORD WINAPI Fun1Proc(LPVOID lpParameter) { char buf[100]; while(g_bRun) { if(tickets<10) { sprintf(buf,"\nthread1 sell ticket = %d",tickets); OutputDebugString(buf); printf(buf); tickets++; } else Sleep(10); } return 0; } DWORD WINAPI Fun2Proc(LPVOID lpParameter) { char buf[100]; while(g_bRun) { if(tickets<10) { sprintf(buf,"\nthread2 sell ticket = %d",tickets); OutputDebugString(buf); printf(buf); tickets++; } else Sleep(10); } return 0; } int main(int argc, char* argv[]) { CreateThread(NULL,0,Fun1Proc,NULL,0,NULL); CreateThread(NULL,0,Fun2Proc,NULL,0,NULL); Sleep(2000); system("PAUSE"); g_bRun = FALSE; return 0; }
理论上输出应该是
- C/C++ code
thread2 sell ticket = 0 thread1 sell ticket = 1 thread2 sell ticket = 2 thread1 sell ticket = 3 thread2 sell ticket = 4 thread1 sell ticket = 5 thread2 sell ticket = 6 thread1 sell ticket = 7 thread2 sell ticket = 8 thread1 sell ticket = 9
实际上却是这样
- C/C++ code
thread1 sell ticket = 0 thread1 sell ticket = 0 thread2 sell ticket = 0 thread1 sell ticket = 1 thread2 sell ticket = 2 thread1 sell ticket = 3 thread2 sell ticket = 4 thread1 sell ticket = 5 thread2 sell ticket = 6 thread1 sell ticket = 7 thread2 sell ticket = 8 thread1 sell ticket = 9
最奇怪的地方是
thread1 sell ticket = 0
thread1 sell ticket = 0
请高手解惑
------解决方案--------------------
当两个线程同时输出字符串时,会有什么结果?
别以为只有变量需要线程安全,一切“唯一”的东西都需要保证线程安全,包括输出
------解决方案--------------------
volatile 不是用来做临界区的。
而是告知编译器这个符号是易变的。
这样编译器就会假定她使用之间需要检测这个易变性。
比如,需要重新读取,或者不对与之关联的语句进行调整顺序等优化。
我用 volatile 的很大原因就是可以保证因果关系。
------解决方案--------------------
------解决方案--------------------
volatile本来就不是给你拿来做线程同步的。
volatile显式要求lvalue conversion时从对象存储的内存的取值,而非之前取到过的(例如放在cache里的)值。对于一些底层操作,如映射硬件存储,中断处理等场合是必要的。至于多线程,用volatile是有可能解决【一小部分】一致性问题,但会严重阻碍优化。