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
的加载将不晚于 *p2
和 data
的加载。
所以我不明白我们在这里还有什么进一步的承诺?
这个 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
是原子写入和读取的,因为它是原子的。该代码中没有其他保证或承诺。
我一直在阅读 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
的加载将不晚于 *p2
和 data
的加载。
所以我不明白我们在这里还有什么进一步的承诺?
这个 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
是原子写入和读取的,因为它是原子的。该代码中没有其他保证或承诺。