代码之家  ›  专栏  ›  技术社区  ›  Curious

STD::MyMyYORYORD轻松和初始化

  •  0
  • Curious  · 技术社区  · 7 年前

    以下内容是否保证先打印1再打印2?

    auto&& atomic = std::atomic<int>{0};
    std::atomic<int>* pointer = nullptr;
    
    // thread 1
    auto&& value = std::atomic<int>{1};
    pointer = &value;
    atomic.store(1, std::memory_order_relaxed);
    while (atomic.load(std::memory_order_relaxed) != 2) {}
    cout << value.load(std::memory_order_relaxed) << endl;
    
    // thread 2
    while (atomic.load(std::memory_order_relaxed) != 1) {}
    cout << pointer->load(std::memory_order_relaxed); << endl;
    pointer->fetch_add(1, std::memory_order_relaxed);
    atomic.store(2, std::memory_order_relaxed) {}
    

    如果没有,这里可能的输出是什么?对于这种情况,标准对初始化和内存顺序说了什么?

    1 回复  |  直到 7 年前
        1
  •  4
  •   curiousguy12    7 年前

    正如在注释中所提到的,使用“宽松”排序可以防止任何必要的线程间同步,因此,访问 pointer 未同步(或无序)。
    这意味着线程2可能会取消引用 指针 尽管它仍然有价值 nullptr .
    还有,因为 指针 是非原子类型(即常规指针),不能在线程之间以这种方式访问。 从技术上讲,您有一个数据竞争,这会导致未定义的行为。

    解决方法是稍微加强内存排序。我认为在 atomic 应该足够:

    auto&& atomic = std::atomic<int>{0};
    std::atomic<int>* pointer = nullptr;
    
    // thread 1
    auto&& value = std::atomic<int>{1};
    pointer = &value;
    atomic.store(1, std::memory_order_release);
    while (atomic.load(std::memory_order_acquire) != 2) {}
    cout << value.load(std::memory_order_relaxed) << endl;
    
    // thread 2
    while (atomic.load(std::memory_order_acquire) != 1) {}
    cout << pointer->load(std::memory_order_relaxed); << endl;
    pointer->fetch_add(1, std::memory_order_relaxed);
    atomic.store(2, std::memory_order_release) {}
    

    有了这个订单,结果就可以打印出来了。

    1
    2