【发布时间】:2015-05-20 09:37:17
【问题描述】:
注意!
我显然没有向这里的每个人清楚地表达我的观点,这令人难以置信的沮丧。我的目标是消除
volatile实际上是一个无操作的神话,它什么都不做。我并不是要说它应该被使用,它是必不可少的,它不是多余的,等等。我已经证明
volatile仍然可以做某事。我承认在某些情况下它是多余的,并且多线程示例是一个糟糕的选择。我也不想隐瞒我的答案的初始修订包含错误的事实。但这个问答甚至还没有达到预期目的。为此,我认为是时候把它扔掉了。
感谢 Kerrek 和 T.C.为他们的见解。我只是不认为他们的回答符合我想问的问题。我敢肯定这是我问得不好的错。
所以我放弃了!并把它作为问题的副本关闭,而不是它的意图,而是它已被解释为。
干杯! (&hth.)
我正在一个线程中写入一个变量并在另一个线程中读取它。有人告诉我 volatile 对此完全没用,除非我使用硬件,否则我不需要在这个时代使用它。
int x = 0;
void thread1()
{
while (true) {
sleep(1);
if (x > 0)
break;
}
}
void thread2()
{
while (true) {
sleep(1);
x++;
}
}
在这种情况下使用volatile 有什么好处吗?
如果x 不是一个简单的int 而是一个类类型呢?
【问题讨论】:
-
注意:这个问题是由一些激烈的争论引起的。关于
volatile的一般主题有几个问题,但我觉得没有人真正专门针对volatile在现代多线程代码中没有位置的误解。但是,我在回答中引用了两个部分相关的现存问题。 -
@LightnessRacesinOrbit 当然
volatile“在现代多线程代码中占有一席之地”!即使这样的代码至少需要与编译器做出的有保证的非优化假设进行交互。无论是硬件行为,还是某些东西的无锁实现。 -
附带说明,
volatile通常与可以自行更改的外围寄存器一起使用。例如,您的代码可能需要像while(STATUS & 0x80);这样的自旋循环(其中STATUS类似于volatile uint8_t& STATUS{*reinterpret_cast<uint8_t*>(0x40F00010)};,并且您不希望它优化为if(STATUS & 0x80) while(1);,如果STATUS不是volatile,就会发生这种情况并且编译器决定将它读入一次寄存器,然后不再获取它。与驱动程序一起玩。 -
我从来没有遇到过它什么都不做的神话。我遇到的唯一神话是它可以用来避免线程之间的数据竞争。可移植,它不能(尽管在某些平台上会出现这种情况),并且尝试这样做只会给出更微妙的未定义行为。 (在这种情况下,如果
x在修改期间短暂地取了一个无效值,或者如果对一个线程的内存视图的更改从未传播到另一个线程,它可能会失败。) -
isvolatileusefulwiththreads.com(点击C++有几个权威参考)
标签: c++ multithreading c++11 volatile