与.有关的问题volatile
在多线程上下文中,它不提供全我们需要的保证。它确实有一些我们需要的属性,但并不是所有的属性,所以我们不能依赖它们。volatile
独处.
但是,我们必须使用的原语残存属性还提供了volatile
是的,所以实际上是不必要的。
对于共享数据的线程安全访问,我们需要保证:
- 读/写实际上发生了(编译器将不只是将值存储在寄存器中,并将更新主内存推迟到很久以后)。
- 不会重新排序。假设我们使用
volatile
变量作为标志,指示是否准备读取某些数据。在我们的代码中,我们只是在准备数据之后设置标志,所以所有相貌
很好。但是,如果指令被重新排序,以设置标志呢?第一?
volatile
确实保证了第一点。它还保证不会发生重排序。在不同的易失性读/写之间..全volatile
内存访问将按指定的顺序进行。这就是我们所需要的volatile
用于:操作I/O寄存器或内存映射硬件,但它无助于多线程代码中的volatile
对象通常仅用于同步对非易失性数据的访问。这些访问仍然可以相对于volatile
一张。
防止重新排序的解决方案是使用记忆屏障,它向编译器和CPU指示在这一点上,不能对内存访问进行重新排序。..在易失性变量访问周围设置这样的屏障,可以确保即使是非易失性访问也不会在易失性访问中被重新排序,从而允许我们编写线程安全的代码。
然而,记忆障碍也确保在达到障碍时执行所有挂起的读/写,因此它有效地为我们自己提供了我们所需要的一切,volatile
没有必要。我们可以移除volatile
完全是限定符。
从C+11开始,原子变量(std::atomic<T>
)给我们所有相关的保证。