volatile 与诡异事件
来源:互联网 发布:java编程小游戏 编辑:程序博客网 时间:2024/04/25 12:47
下面是我遇到的一个多线程程序中诡异事件的解决过程:主线程main启动 thread1 和 thread2,thread2保持阻塞,接到thread1发出的信号后工作,完毕后发出终了信号通知thread1,再次阻塞...直到thread1发出结束信号为止。代码如下:(信号用全局变量实现)
thread.h
thread.c
thread1.c
thread2.c
编译:
#gcc -o Thread thread.c thread1.c thread2.c -pthread
运行,正常结果是(指的是不会卡住,某些步骤会有先后变化)
#./Thread
thread1---thread1 start
thread1---send_task: 1
thread2---thread2 start
thread2---hanging and waiting...
thread2---got task: 1
thread2---Haahahhahahah!~
thread2---hanging and waiting...
thread1---send_task: 2
thread2---got task: 2
thread2---OhhAhhhOhhhhh!~
thread2---hanging and waiting...
thread1---send_task: 3
thread2---got task: 3
thread2---I'm dying...!~
thread2---thread2 over
thread1---thread1 over
Thread 1 returns: 0
Thread 2 returns: 0
但是结果多变,常常卡在
(thread2 运行越慢,越易重现,所以我故意在thread2.c 内加入 sleep(3);)
程序逻辑没问题,不存在死锁,为什么会卡在上面两步?明明 task_ready 已由 thread2 修改过了,thread1的这个语句
为什么”不知道“?为什么一个线程察觉不到别的线程对公共全局变量的修改?这时候,忽然想到了一个从未用过的很奇特的限定符(qualifier)volatile:通知编译器,即使当前的程序(进程/线程)未修改它所标识的变量,此变量值也会改变。(可能其他程序/线程/硬件修改这个变量)。
为什么需要通知?先看看一句代码的汇编实现:(是用ARM实现的,我的机器是AMD64的,这两句没产生优化)
因为,有时,编译器会对频繁使用的变量或者它认为“不会改变”的变量进行优化,对变量取值时不是从每次从内存-->寄存器;
而是直接一次取出保存在寄存器内,以后直接从寄存器取。问题就在于此:"似乎"不会改变的 task_ready和 main_task会被
thread2所修改,此处的“优化”就是问题所在,解决方式就是相关变量加上volatile即可。
- volatile 与诡异事件
- 诡异的volatile
- 诡异的回车事件
- core dump的诡异事件
- 诡异事件之自定义UINavigationController
- svn合并时候的诡异事件
- FORM中诡异的VALIDATE事件
- Oledb更新Access数据的诡异事件
- python sqlite数据库的诡异事件
- 关于php的GearmanClient的诡异事件
- js的事件方法感觉比较诡异
- popstate事件在webkit中的诡异行为
- popstate事件在webkit中的诡异行为
- JAVA+=运算程序诡异事件
- 诡异的谈话与思索
- CDOJ1328 卿学姐与诡异村庄
- 诡异
- 诡异
- Intent 初步了解
- SQL 10 函数 1 数学函数
- Cmake入门
- Yahoo!网站性能最佳体验的34条黄金守则——服务器
- Vim(1) 编译与错误定位
- volatile 与诡异事件
- C#总结心得
- 优化浏览器渲染
- .net3.5下的Socket通信框架
- 如何使CSS渲染更高效
- 网络安全:拦截文件也要封锁网址
- SQL Server 2000 从数据库中按日期提取datetime数据
- 原子间单量子能量交换首实现 简化信息处理过程
- Eclipse Android代码助手缓慢的解决方法