为什么volatile会产生未定义的行为

时间:2017-02-01 10:44:17

标签: c++ undefined-behavior volatile

根据我的理解,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,我可以理解为什么这本书说“他们可能会看到任何东西”?

2 个答案:

答案 0 :(得分:7)

本节讨论volatile对多线程编程安全的常见误解。如果不同的线程同时读取和写入vi,那么您将拥有数据竞争,因为没有适当的同步或原子性保证。数据竞争是C ++中未定义的行为,所以&#34;任何&#34;真的有意义。

如果使用了正确的原子操作,那么可以保证对vi的所有修改都不会被其他线程中断,因此你没有数据竞争,你的程序也是安全的。或者,可以使用互斥锁或类似方法引入同步。

请参阅this site上的参考资料,详细了解volatile对此类事件不安全的原因。

答案 1 :(得分:0)

有些硬件实现可能有两个带有共享异步内存的处理器,这似乎是合理的。如果一个处理器恰好在另一个处理器正在尝试读取它时写入一个值,那么这些位可能在读取操作的中间字面改变,这样第二个处理器就会看到新旧值的任意混合。更糟糕的是,某些处理器可能出现故 如果由于称为亚稳态的硬件问题而导致值被精确读取,则会很糟糕。

任何可以运行C ++的机器是否会出现这样的亚稳态问题[硬件设计师在过去的35年里已经学到了很多关于如何避免它们的问题],该标准的作者并不想强加要求合理的要求实施会遇到麻烦。