繁体   English   中英

C ++内存订购一致性

[英]C++ Memory Ordering Consistency

假设我有以下代码:

void* p0 = nullptr;
void* p1 = alloc_some_data();
void f1() {
    p0 = p1;
    p1 = nullptr;
}

假设f1在线程1上运行。是否有可能(保留代码)另一个线程可能在某些时候将p0p1视为nullptr (如果编译器或硬件重新排序指令,例如第二个赋值发生在第一个之前)?

我问这个的原因是因为我想实现一个垃圾收集器,我想知道我是否需要使用原子指令( std::atomic )从GC线程访问指针。 如果GC线程看到p0 == p1 == alloc_some_data()没有问题,但是如果GC线程看到p0 == p1 == nullptr会有问题,因为它会将先前在p1中的数据报告为无法到达时显然是到达。

如果您在一个线程中读取一个由另一个线程写入而没有同步的对象,则会有数据竞争。 这显然意味着您的垃圾收集器需要使用某种同步来读取值。 关于你原来的问题:代码中没有任何内容表明在写入p1之前写入p0变得可见,即另一个线程确实可以看到两者都为空。 这与用于与另一个线程通信的同步原语无关:这两个写操作之间没有排序。

是。 虽然不一定可能,但完全有可能,因为这些操作不是原子的。

一个(几种可能的情况)是这样的:

Thread 2: Get value of p0 (null)

Thread 1: Get value of p1 (non-null)
          p0 = p1
          p1 = nullptr

Thread 2: Get value of p1 (null)

您需要使用某种形式的访问控制( 互斥锁)。

您的问题的答案是肯定的,但它依赖于编译器和CPU。 我认为你还需要让p0p1变得不稳定。 要停止重新排序,可以使用_mm_sfence_mm_lfence (对于x86 / x64)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM