Sou*_*a B 5 c++ multithreading synchronization atomic memory-barriers
下面是用于跨线程数据同步的获取-释放语义的简单示例。
// thread 1 // thread 2
data = 100;
flag.store(true, std::memory_order_release);
while(!flag.load(std::memory_order_acquire));
assert(data == 100);
Run Code Online (Sandbox Code Playgroud)
据我了解,这准确地表明了获取-释放内存顺序的使用,并且程序将按预期工作。
但如果我使用独立屏障会怎样?
// thread 1 // thread 2
data = 100;
std::atomic_thread_fence(std::memory_order_release);
flag.store(true, std::memory_order_relaxed);
while(!flag.load(std::memory_order_relaxed))
std::atomic_thread_fence(std::memory_order_acquire);
assert(data == 100);
Run Code Online (Sandbox Code Playgroud)
我一直认为这与第一个例子完全相同。
但今天我在 CppCon 上观看了 Herb Sutter 的演讲(C++ and Beyond 2012:Herb Sutter - 原子武器)。在视频中的1:07:10 ,他举了一个例子来说明独立围栏的效果并不理想。看完后我很困惑。
例子是这样的:
// thread 1 // thread 2
widget *temp = new widget();
XX mb(); XXXXXXXXXXXXXXXXXXXXX // a
global = temp;
temp2 = global;
XX mb(); XXXXXXXXXXXXXXXXXXXXX // b
temp2->do_something();
temp2 = global;
XX mb(); XXXXXXXXXXXXXXXXXXXXX
temp2->do_something_else();
Run Code Online (Sandbox Code Playgroud)
他说,在 a 和 b 处,您需要一个完整的屏障,而不仅仅是释放和获取,因为它们与任何特定的存储或负载无关。此外,他表示,独立的获取和释放障碍没有任何意义。它是否正确?(为了简单起见,假设对global的读取和写入是不可分割的,即global永远不包含撕裂值)。
为什么这不起作用?
// thread 1 // thread 2
widget *temp = new widget();
XX release(); XXXXXXXXXXXXXXXX // a
global = temp;
temp2 = global;
XX acquire(); XXXXXXXXXXXXXXXX // b
temp2->do_something();
temp2 = global;
XX acquire(); XXXXXXXXXXXXXXXX
temp2->do_something_else();
Run Code Online (Sandbox Code Playgroud)