我对 std::memory_order_acquire
和 std::memory_order_release
的理解如下:
Acquire 的意思是,在 acquire fence 之后的内存访问不能被重排序到 fence 之前。
Release 的意思是,在 release fence 之前的内存访问不能被重排序到 fence 之后。
然而,我不理解为什么在 C++11 原子库中,acquire fence 与 load 操作相关联,而 release fence 与 store 操作相关联。
需要澄清的是,C++11 <atomic>
库使您可以通过两种方式指定内存栅栏:一种是将栅栏作为原子操作的额外参数指定,例如:
x.load(std::memory_order_acquire);
或者您可以使用 std::memory_order_relaxed
并分别指定栅栏,例如:
x.load(std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_acquire);
我不理解的是,鉴于上述"acquire"和"release"的定义,为什么C++11会将acquire与load相关联,并将release与store相关联?是的,我看过许多示例,展示了如何使用acquire/load与release/store之间进行线程同步,但总体而言,似乎acquire fences(防止语句后内存重排序)和release fences(防止语句前内存重排序)的概念与loads和stores的概念是正交的。那么,例如,为什么编译器不允许我这样说:
x.store(10, std::memory_order_acquire);
我意识到我可以通过使用 memory_order_relaxed
,然后分别使用一个单独的 atomic_thread_fence(memory_order_acquire)
语句来实现上述目标,但是,为什么不能直接使用带有 memory_order_acquire
的存储呢?
这种情况的可能用例是,如果我想确保某个存储(比如 x = 10
)在执行可能影响其他线程的其他语句之前发生。
atomic_thread_fence(std::memory_order_acquire)
是一个真正的栅栏。请参阅标准中的 **1.10:5 Multi-threaded executions and data races [intro.multithread]**,该标准规定(引用草案n3797):“没有关联内存位置的同步操作是一个栅栏,可以是获取栅栏、释放栅栏或获取和释放栅栏。”相比之下,x.load(std::memory_order_acquire)
是一个原子操作,它对x
执行了一个获取操作,如果该值与存储到x
的释放操作匹配,则它将成为一个同步操作。 - amdn