为什么挥发性没有考虑在多线程C或C ++编程有用吗? [英] Why is volatile not considered useful in multithreaded C or C++ programming?
问题描述
如这个答案我最近公布的论证,我似乎混淆了的实用程序(或缺乏)挥发性
在多线程编程环境。
As demonstrated in this answer I recently posted, I seem to be confused about the utility (or lack thereof) of volatile
in multi-threaded programming contexts.
我的理解是这样的:任何时间的变量可以一块code的控制流外修改访问它,该变量应声明为挥发性
。信号处理,I / O寄存器和变量被另一个线程修改的所有构成了此类情况。
My understanding is this: any time a variable may be changed outside the flow of control of a piece of code accessing it, that variable should be declared to be volatile
. Signal handlers, I/O registers, and variables modified by another thread all constitute such situations.
所以,如果你有一个全局的INT 富
和富
是由一个线程读取和原子方式设置另一个线程(可能使用合适的机器指令),读出线程看到这种情况的相同方式它看到由一个信号处理器调整或修改由外部硬件条件,从而富$ C的可变$ C>应申报
挥发性
(或者,多线程的情况下,内存围栏负载,这可能是一个更好的解决方案访问)。
So, if you have a global int foo
, and foo
is read by one thread and set atomically by another thread (probably using an appropriate machine instruction), the reading thread sees this situation in the same way it sees a variable tweaked by a signal handler or modified by an external hardware condition and thus foo
should be declared volatile
(or, for multithreaded situations, accessed with memory-fenced load, which is probably a better a solution).
如何以及在哪里我错了?
How and where am I wrong?
推荐答案
有问题挥发性
在多线程的上下文是它不提供的所有的我们所需要的保证。它有我们需要的一些属性,但不是所有的人,所以我们不能依靠挥发性
的单独的
The problem with volatile
in a multithreaded context is that it doesn't provide all the guarantees we need. It does have a few properties we need, but not all of them, so we can't rely on volatile
alone.
不过,原语我们不得不使用的的剩余的特性还提供了的那些挥发性
做,所以它是有效的不必要的
However, the primitives we'd have to use for the remaining properties also provide the ones that volatile
does, so it is effectively unnecessary.
有关线程安全的访问共享数据,我们需要一个保证:
For thread-safe accesses to shared data, we need a guarantee that:
- 读/写实际情况(编译器将不只是存储在寄存器中,而不是价值,并推迟升级主内存,直到很久以后)
- 没有重新排序发生。假设我们使用
挥发性
变量作为一个标志来指示某些数据是否已准备好被读取。在我们的code,我们只需设置preparing数据后旗,所以所有的看起来的罚款。但是,如果指令重新排序,以便设置了标志的第一个的?
- the read/write actually happens (that the compiler won't just store the value in a register instead and defer updating main memory until much later)
- that no reordering takes place. Assume that we use a
volatile
variable as a flag to indicate whether or not some data is ready to be read. In our code, we simply set the flag after preparing the data, so all looks fine. But what if the instructions are reordered so the flag is set first?
挥发性
并保证第一点。同时也保证了发生的之间不同的挥发性读/写的任何重新排序。所有挥发性
内存访问将发生在他们所指定的顺序。这是我们需要什么挥发性
适用于:操作I / O寄存器或内存映射的硬件,但它并不能帮助我们在多线程code其中在挥发性
对象通常仅用于同步访问非易失性数据。这些访问仍然可以相对挥发性
的人重新排序。
volatile
does guarantee the first point. It also guarantees that no reordering occurs between different volatile reads/writes. All volatile
memory accesses will occur in the order in which they're specified. That is all we need for what volatile
is intended for: manipulating I/O registers or memory-mapped hardware, but it doesn't help us in multithreaded code where the volatile
object is often only used to synchronize access to non-volatile data. Those accesses can still be reordered relative to the volatile
ones.
要preventing重新排序的解决方案是使用的内存屏障的,这既表明编译器和CPU的的没有内存访问可能会碰到这个点进行重新排序。配售围绕我们volatile变量访问这些壁垒保证了即使非挥发性访问不会跨越挥发之一重新排序,使我们能够编写线程安全的code。
The solution to preventing reordering is to use a memory barrier, which indicates both to the compiler and the CPU that no memory access may be reordered across this point. Placing such barriers around our volatile variable access ensures that even non-volatile accesses won't be reordered across the volatile one, allowing us to write thread-safe code.
然而,记忆障碍也的确保所有未决读取/到达屏障时,写操作被执行,因此它有效地为我们提供了我们需要通过自身的一切,使挥发性
不必要的。我们可以只删除挥发性
预选赛完全。
However, memory barriers also ensure that all pending reads/writes are executed when the barrier is reached, so it effectively gives us everything we need by itself, making volatile
unnecessary. We can just remove the volatile
qualifier entirely.
由于C ++ 11,原子变量(的std ::原子< T>
)。给我们所有相关的担保
Since C++11, atomic variables (std::atomic<T>
) give us all of the relevant guarantees.
这篇关于为什么挥发性没有考虑在多线程C或C ++编程有用吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!