从 C++ 中的另一个线程读取指针

Posted

技术标签:

【中文标题】从 C++ 中的另一个线程读取指针【英文标题】:Reading pointers from another thread in C++ 【发布时间】:2017-02-23 11:47:57 【问题描述】:

在下面的代码中,线程 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

但是在下面的代码中,*x 在线程 2 中总是 10 吗?

int* x = new int;
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); // will *x always be 10?

【问题讨论】:

我几乎看不出有什么不同。而且我认为由于原子布尔访问,不需要内存围栏。 【参考方案1】:

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

这里不需要内存栅栏,因为b = true 本质上是b.store(true, std::memory_order_seq_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;

是一样的:

f():
        movl    $10, x(%rip)
        movb    $1, b(%rip)
        mfence
        ret
g():
        movl    $10, x(%rip)
        movb    $1, b(%rip)
        mfence
        ret

在您的特定情况下,在我看来,您只需要将std::memory_order_release 存储到b 就可以使存储到x 也对其他线程可见,围栏是不必要的。 IE。 b.store(true, std::memory_order_release) 在这里就足够了。消费者代码需要做b.load(std::memory_order_acquire)

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

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

【讨论】:

评论不用于扩展讨论;这个对话是moved to chat。

以上是关于从 C++ 中的另一个线程读取指针的主要内容,如果未能解决你的问题,请参考以下文章

C++ 指针读取内存为 0

从内存中读取图像,知道指向内存的指针。 VC++ [关闭]

Java之多线程断点下载的实现

使用 OpenCV 将视频帧读取到指定的指针(C++)

在 C++ 中从文件末尾读取的最有效方法是啥? (解析文件中的最后 128 位)

多线程jpa读取时休眠空指针异常