为什么挥发性没有考虑在多线程C或C ++编程有用吗? [英] Why is volatile not considered useful in multithreaded C or C++ programming?

查看:108
本文介绍了为什么挥发性没有考虑在多线程C或C ++编程有用吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个答案我最近公布的论证,我似乎混淆了的实用程序(或缺乏)挥发性在多线程编程环境。

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 是由一个线程读取和原子方式设置另一个线程(可能使用合适的机器指令),读出线程看到这种情况的相同方式它看到由一个信号处理器调整或修改由外部硬件条件,从而应申报挥发性(或者,多线程的情况下,内存围栏负载,这可能是一个更好的解决方案访问)。

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆