根据我的理解,volatile
- 合格的价值意味着无论何时访问它们,我们都必须访问收件人并获取最新值。
现在我正在阅读 Effective Modern C ++ 这本书,我不明白为什么volatile
在这里创建了一个UB:
volatile int vi(0); // initialize vi to 0
vi = 10; // set vi to 10
std::cout << vi; // read vi's value
++vi; // increment vi to 11
vi--; // decrement vi to 10
在执行此代码期间,如果其他线程正在读取该值 vi,他们可能会看到任何东西(例如,-12,68,4090727-任何东西!)。这样的代码会有未定义的行为,因为这些语句会修改vi,所以如果其他线程同时读取vi,那么同时存在的读取器和写入器既不是std :: atomic也不是由互斥锁保护,这就是定义数据竞赛。
在我看来,如果其他主题可能看到0,10或11,我可以理解为什么这本书说“他们可能会看到任何东西”?
答案 0 :(得分:7)
本节讨论volatile
对多线程编程安全的常见误解。如果不同的线程同时读取和写入vi
,那么您将拥有数据竞争,因为没有适当的同步或原子性保证。数据竞争是C ++中未定义的行为,所以&#34;任何&#34;真的有意义。
如果使用了正确的原子操作,那么可以保证对vi
的所有修改都不会被其他线程中断,因此你没有数据竞争,你的程序也是安全的。或者,可以使用互斥锁或类似方法引入同步。
请参阅this site上的参考资料,详细了解volatile
对此类事件不安全的原因。
答案 1 :(得分:0)
有些硬件实现可能有两个带有共享异步内存的处理器,这似乎是合理的。如果一个处理器恰好在另一个处理器正在尝试读取它时写入一个值,那么这些位可能在读取操作的中间字面改变,这样第二个处理器就会看到新旧值的任意混合。更糟糕的是,某些处理器可能出现故 如果由于称为亚稳态的硬件问题而导致值被精确读取,则会很糟糕。
任何可以运行C ++的机器是否会出现这样的亚稳态问题[硬件设计师在过去的35年里已经学到了很多关于如何避免它们的问题],该标准的作者并不想强加要求合理的要求实施会遇到麻烦。