std::atomic<int> cnt = {2};

thread 1:
    doFoo();
    if (cnt.fetch_sub(1, std::memory_order_relaxed) == 1) {
      doBazz();
    }

thread 2:
    doBar();
    if (cnt.fetch_sub(1, std::memory_order_relaxed) == 1) {
        doBazz();
    }

我们可以保证doFoo()doBar()总是在doBazz()之前发生吗?

最佳答案

您显示的代码中根本没有内存排序,因此保证不成立。但是,可以通过使fetch_sub成为release sequence的一部分来使用宽松的排序方式并使其正常工作:

std::atomic<int> cnt{0};
cnt.store(2, std::memory_order_release); // initiate release sequence (RS)

//thread 1:
    doFoo();
    if (cnt.fetch_sub(1, std::memory_order_relaxed) == 1) { // continue RS
        std::atomic_thread_fence(std::memory_order_acquire); // synchronizes with RS
        doBazz();
    }

//thread 2:
    doBar();
    if (cnt.fetch_sub(1, std::memory_order_relaxed) == 1) { // continue RS
        std::atomic_thread_fence(std::memory_order_acquire); // synchronizes with RS
        doBazz();
    }

或者
void doBazz();

std::atomic<int> cnt{0};
cnt.store(2, std::memory_order_release); // initiate release sequence (RS)

//thread 1:
    doFoo();
    if (cnt.fetch_sub(1, std::memory_order_relaxed) == 1) { // continue RS
        doBazz();
    }

//thread 2:
    doBar();
    if (cnt.fetch_sub(1, std::memory_order_relaxed) == 1) { // continue RS
        doBazz();
    }

void doBazz() {
    std::atomic_thread_fence(std::memory_order_acquire); // synchronizes with RS
    // ...
}

这些保证doFoo()doBar()始终在doBazz()之前发生。

关于c++ - fetch_sub与memory_order_relaxed的原子引用计数?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38448886/

10-11 00:57