打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
volatile

潘爱民<<程序员自我修炼>>里面的问题,

int a=0;

thread1:
Lock();
++a;
UnLock();

thread2:
Lock();
++a;
UnLock();

锁只能保证同一时间只有一个++a在执行,它不能应付下面这种情况:
线程1:得到锁,把a读到寄存器,++a,释放锁
线程2:得到锁,++a,释放锁,把值从寄存器写回内存
线程1再把值从寄存器写回内存

落后的编译器的“过度优化”造成的可能的问题,一般的release选项是不会造成这种问题的,而且造成这种问题不是代码的错,而是编译器的错。我记得以前看过的书也写过double lock check也一样有可能被优化出错,但是这种情况我们是没有什么办法的。

请看下面的程序:

C/C++ code?
1
2
3
4
5
6
7
int * ptr = getPointer();
 
cout << *ptr << endl; //我们假设这个输出为0,也就是*ptr的运算结果为0
 
//这个时候,某一线程将*ptr加1
 
cout << *ptr << endl; //这是第二次输出,但结果可能是1也可能是0


为什么第二次的输出不一定是1?实际上,不少人用的编译器关闭优化是1,打开优化却变为0。
当你打开优化时,第二次输出所使用的值不一定来自ptr所指向的内存,很有可能是缓存到寄存器里的值,
编译器之所以这样做,是因为它根本不知道两次输出之间*ptr的值会改变,因为两次输出之间确实没什么代码。
如果这样写:
int volatile * ptr = getPointer();
就不会有这种问题,因为volatile会告诉编译器,ptr所指向的数据随时都会改变(volatile的具体意义与编译器相关,但它的大体意思与const相反,其用法与const一样)。

volatile是为了多线程不用加锁直接取值而设置的。

volatile只用在int,char,short,long这些原子取值的类型上,而不会用在结构体等复杂类型上!  复杂类型在多线程共享式必须用锁,volatile是没作用的,否则会破坏数据结构了
所以volatile和原子性是有联系的!! LZ也不用担心,代码没问题!

volatile防止编译器乱搞
可用读写栅栏(_WriteBarrier 和 _ReadBarrier之类)代替,效率会高些

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
volatile作用
C语言中关键字volatile追根问底
C语言丨深入理解volatile关键字
volatile的作用
详细解释 volatile
嵌入式研发工程师面试大全(ANSI CC++知识 )
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服