gpt4 book ai didi

c++ - 理解 C++11 中的 `memory_order_acquire` 和 `memory_order_release`

转载 作者:行者123 更新时间:2023-12-01 15:13:40 24 4
gpt4 key购买 nike

我正在阅读 the documentation更具体地说

memory_order_acquire: A load operation with this memory order performs the acquire operation on the affected memory location: no reads or writes in the current thread can be reordered before this load. All writes in other threads that release the same atomic variable are visible in the current thread (see Release-Acquire ordering below).

memory_order_release: A store operation with this memory order performs the release operation: no reads or writes in the current thread can be reordered after this store. All writes in the current thread are visible in other threads that acquire the same atomic variable (see Release-Acquire ordering below) and writes that carry a dependency into the atomic variable become visible in other threads that consume the same atomic (see Release-Consume ordering below)

这两个位:

来自memory_order_acquire

... no reads or writes in the current thread can be re-ordered before this load...

来自memory_order_release

... no reads or writes in the current thread can be re-ordererd after this store...

它们到底是什么意思?

还有这个例子

#include <thread>
#include <atomic>
#include <cassert>
#include <string>

std::atomic<std::string*> ptr;
int data;

void producer()
{
std::string* p = new std::string("Hello");
data = 42;
ptr.store(p, std::memory_order_release);
}

void consumer()
{
std::string* p2;
while (!(p2 = ptr.load(std::memory_order_acquire)))
;
assert(*p2 == "Hello"); // never fires
assert(data == 42); // never fires
}

int main()
{
std::thread t1(producer);
std::thread t2(consumer);
t1.join(); t2.join();
}

但我无法真正弄清楚我引用的这两个位在哪里适用。我了解发生了什么,但我并没有真正看到重新排序位,因为代码很小。

最佳答案

一个线程完成的工作不保证对其他线程可见。

为了使数据在线程之间可见,需要一种同步机制。可以使用非宽松的 atomicmutex 。它被称为获取-释放语义。编写互斥锁会“释放”它之前的所有内存写入,读取相同的互斥锁会“获取”这些写入。

这里我们使用 ptr 将到目前为止完成的工作(data = 42)“释放”到另一个线程:

    data = 42;
ptr.store(p, std::memory_order_release); // changes ptr from null to not-null

在这里我们等待,通过这样做我们同步(“获取”)生产者线程完成的工作:

    while (!ptr.load(std::memory_order_acquire)) // assuming initially ptr is null
;
assert(data == 42);

注意两个不同的 Action :

  1. 我们在线程之间等待(同步步骤)
  2. 作为等待的副作用,我们将工作从提供者转移到消费者(提供者释放和消费者获得它)

在没有 (2) 的情况下,例如使用 memory_order_relaxed 时,仅同步 atomic 值本身。之前/之后完成的所有其他工作都不是,例如data 不一定包含 42 并且在地址 p 处可能没有完整构造的 string 实例(如消费者所见)。

有关获取/释放语义和 C++ 内存模型的其他细节的更多详细信息,我建议观看 Herb 的优秀 atomic<> weapons talk ,虽然很长,但是看着很有趣。更详细的信息还有一本名为“C++ Concurrency in Action”的书

关于c++ - 理解 C++11 中的 `memory_order_acquire` 和 `memory_order_release`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59626494/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com