C++ 在C++;

C++ 在C++;,c++,multithreading,pointers,atomicity,C++,Multithreading,Pointers,Atomicity,在下面的代码中,由于原子线程围栏,线程2中的x的值始终为10 int x; atomic<bool> b(false); // thread 1: x = 10; atomic_thread_fence(memory_order_release); b = true; // thread 2: while(!b){} atomic_thread_fence(memory_order_acquire); assert(x == 10); // x will always be 10

在下面的代码中,由于原子线程围栏,线程2中的
x
的值始终为10

int x;
atomic<bool> b(false);

// thread 1:
x = 10;
atomic_thread_fence(memory_order_release);
b = true;

// thread 2:
while(!b){}
atomic_thread_fence(memory_order_acquire);
assert(x == 10); // x will always be 10

在这两种情况下,您都会得到
10
,这里的存储是直接完成的还是通过指针完成的没有区别

这里不需要内存围栏,因为
b=true
本质上是
b.store(true,std::memory\u order\u seq\u cst)
-带围栏的获取发布

这样的内存顺序可以防止编译器对操作周围的存储和加载进行重新排序,并使前面的存储在该存储可见时对其他线程可见

如果比较这两个函数的生成代码:

#include <atomic>

int x;
std::atomic<bool> b(false);

void f() {
    x = 10;
    std::atomic_thread_fence(std::memory_order_release);
    b = true;
}

void g() {
    x = 10;
    b = true;
}

但是,在您的特殊情况下,我认为您只需要
std::memory\u order\u release
store to
b
就可以让其他线程也可以看到
x
的存储,所以不需要围栏。例如,
b.store(true,std::memory\u order\u release)
在这里就足够了。消费者代码需要执行
b.load(std::memory\u order\u acquire)

标准互斥锁在锁定时获取内存顺序,在解锁时释放内存顺序(这是术语获取/释放的来源),不涉及任何围栏


很少需要明确的限制,主要是在硬件驱动程序中。在用户空间模式中,由于对C++11内存模型的误解,常常设置代码围栏。围栏是最昂贵的原子同步机制,这是避免使用围栏的主要原因。

我几乎看不出有什么区别。我认为,由于原子布尔访问,不需要内存围栏;这段对话已经结束。
#include <atomic>

int x;
std::atomic<bool> b(false);

void f() {
    x = 10;
    std::atomic_thread_fence(std::memory_order_release);
    b = true;
}

void g() {
    x = 10;
    b = true;
}
f():
        movl    $10, x(%rip)
        movb    $1, b(%rip)
        mfence
        ret
g():
        movl    $10, x(%rip)
        movb    $1, b(%rip)
        mfence
        ret