【发布时间】:2011-01-29 21:50:06
【问题描述】:
正如我最近发布的this answer 中所展示的,我似乎对volatile 在多线程编程上下文中的实用性(或缺乏实用性)感到困惑。
我的理解是:任何时候一个变量可能在一段代码访问它的控制流之外被改变,这个变量应该被声明为volatile。信号处理程序、I/O 寄存器以及被另一个线程修改的变量都构成了这种情况。
因此,如果您有一个全局 int foo,并且 foo 由一个线程读取并由另一个线程以原子方式设置(可能使用适当的机器指令),则读取线程以相同的方式看待这种情况看到由信号处理程序调整的变量或由外部硬件条件修改的变量,因此应将foo 声明为volatile(或者,对于多线程情况,使用内存隔离负载访问,这可能是一个更好的解决方案)。
我哪里错了?
【问题讨论】:
-
所有 volatile 所做的只是说编译器不应该缓存对 volatile 变量的访问。它没有说明序列化这种访问。这已经在这里讨论了不知道多少次了,我认为这个问题不会对这些讨论增加任何内容。
-
@neil 我搜索了其他问题,并找到了一个,但我看到的任何现有解释都没有触发我真正理解为什么我错了的原因。这个问题引出了这样一个答案。
-
如需深入研究 CPU 对数据的处理方式(通过其缓存),请查看:rdrop.com/users/paulmck/scalability/paper/whymb.2010.06.07c.pdf
-
在 Java 中
volatile在读取时会创建一个内存屏障,因此它可以用作方法已结束的线程安全标志,因为它与标志之前的代码强制执行发生前的关系放。在 C 中情况并非如此。 -
@curiousguy 这就是我所说的“C 中不是这种情况”的意思,它可以用于写入硬件寄存器等,并且不像 Java 中常用的那样用于多线程。
标签: c++ c multithreading volatile c++-faq