Synchronize-With 关系到底是什么?

What exactly is Synchronize-With relationship?

我一直在阅读 cpp 参考中的 this post of Jeff Preshing about The Synchronizes-With Relation, and also the "Release-Acquire Ordering" section in the std::memory_order 页,但我不太明白:

似乎有某种标准的承诺,我不明白为什么有必要。让我们以 CPP 参考中的示例为例:

#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();
}

参考文献解释说:

If an atomic store in thread A is tagged memory_order_release and an atomic load in thread B from the same variable is tagged memory_order_acquire, all memory writes (non-atomic and relaxed atomic) that happened-before the atomic store from the point of view of thread A, become visible side-effects in thread B. That is, once the atomic load is completed, thread B is guaranteed to see everything thread A wrote to memory. This promise only holds if B actually returns the value that A stored, or a value from later in the release sequence.

据我了解,当我们

ptr.store(p, std::memory_order_release)

我们实际上做的是告诉编译器和 CPU 当 运行 时,让 data 和内存无法指向by std::string* p 将在 ptr 的新值对线程 t2 可见后可见。

同样,当我们

ptr.load(std::memory_order_acquire)

我们告诉编译器和 CPU:这样 ptr 的加载将不晚于 *p2data 的加载。

所以我不明白我们在这里还有什么进一步的承诺?

这个 ptr.store(p, std::memory_order_release) (L1) 保证在这个特定线程 (T1) 中在这一行之前所做的任何事情都将对其他线程可见,只要其他线程正在读取 ptr正确的方式(在本例中,使用 std::memory_order_acquire)。此保证仅适用于这一对,仅此行不提供任何保证。

现在你在另一个线程 (T2) 上有 ptr.load(std::memory_order_acquire) (L2),它与来自另一个线程的一对一起工作,保证只要它读取写入 T1 中的值,你就可以看到其他值写在该行之前(在您的情况下是 data)。所以因为 L1 L2 同步,data = 42; 发生在 assert(data == 42).

之前

还可以保证 ptr 是原子写入和读取的,因为它是原子的。该代码中没有其他保证或承诺。