c++ - 使用 std::memory_order_acq_rel 和一个原子变量来进行 add/sub/inc/dec 是否足够?

标签 c++ multithreading c++11 arm lock-free

众所周知,使用 Release-Acquire 排序 (std::memory_order_acq_rel) 就足够了当我们仅使用一个原子变量来存储或加载它时:https://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html

但是,对于其他基本的无等待函数(例如:加法、减法、递增和递减)来说也是如此吗?

即对于弱(arm-cpu,...)和强(x86-cpu,...)内存模型,以下 C++ 代码中的 next() 函数是线程安全的吗?需要另一个障碍排序(更低/更高)?

#include <iostream>
#include <atomic>
using namespace std;

class progression_lf {
 public:
 progression_lf() : n(0) {}

 int next() {
    // memory_order_acq_rel - enough, and increases performance for the weak memory models: arm, ...
    int const current_n = n.fetch_add(1, std::memory_order_acq_rel);
    int result = 2 + (current_n - 1)*3;
    return result;
 }

 bool is_lock_free() { return ATOMIC_INT_LOCK_FREE; }

 private:
 std::atomic<int> n;
};

int main() {

    // reference (single thread)
    for(int n = 0; n < 10; ++n) {
        std::cout << (2+(n-1)*3) << ", ";
    }
    std::cout << std::endl;

    // wait-free (multi-thread safety)
    progression_lf p;
    for(int n = 0; n < 10; ++n) {
        std::cout << (p.next()) << ", ";
    }
    std::cout << std::endl; 

    std::cout << "lock-free & wait-free: " << 
        std::boolalpha << p.is_lock_free() << 
        std::endl;

    return 0;
}

最佳答案

如果您的线程只需要一个唯一的数字,那么恐怕您不需要任何比此处宽松的内存排序更强的 C++ 内存排序。原子性就足够了,std::memory_order_relaxed 保证:

Relaxed operation: there are no synchronization or ordering constraints, only atomicity is required of this operation.

事实上,具有原子读取-修改-写入操作的代码仍会在 x86 上生成硬件指令,这意味着完整的内存屏障。

您可以看到不同编译器为不同平台生成的内容 here .

关于c++ - 使用 std::memory_order_acq_rel 和一个原子变量来进行 add/sub/inc/dec 是否足够?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31878133/

相关文章:

java - 如果链中的第一个方法是异步的,则方法调用链(CompletableFuture API)是否会异步执行?

c++ - 返回本地对象右值引用,对还是错?

c++ - 如何使用 winHttp 为用户名设置原始 header ?

iphone - 使用运行循环联网

JavaFX 停止线程

c++ - 类 POD 成员默认初始化与零初始化与无初始化?

c++ - 删除从嵌套包中找到的第一个指定类型

c++ - 带有 std::regex 的巨大程序大小 C++

c++ - boost::posix_time::ptime 是固定大小的吗?

c++ - shared_ptr 和 this 指针