c ++:原子变量的值在保存在局部变量中时无效

c++: atomic variable's value is invalid when saved in local variable

我在一些 Obj-C 文件中定义了原子变量 current:

std::atomic<long long> current;

之后启动:

current=4;

之后,该变量可以通过线程数访问。 一些线程像这样修改了变量:

current=(current.fetch_add(1))%4;

当其他线程以不同方式修改变量时:

current.fetch_add(1);
if(current>=4){
    current=0;
}

最后执行下一行:

long long cs=current;

此时发生了一些奇怪的事情:在调试器中显示 cs 是 4 而 current 有不同的值,通常是 1。 我的期望是 cs 应该有 current 的最新值并且永远不应该大于 3。 我检查了 current 的所有其他实例;它们数量不多,并且在任何地方都可以正确使用。 我错过了什么?

原子值不是同步原语。可能的执行流程之一:

current.fetch_add(1);  // T1
long long cs=current;  // T2
if(current>=4){  // T1
    current=0;
}

auto tmp = current.fetch_add(1);  // T1
long long cs=current;  // T2
current=tmp%4;  // T1

解决方案是在 compare-exchange 中使用互斥锁或自旋锁。

这是在多线程环境下极有可能发生的场景。假设只有 2 个线程,我在这里称为 THREAD-2 的主线程和一个工作线程 THREAD-1。让我们从 current 的值为 3 开始,现在它被 THREAD-1 递增,而 THREAD-2 正在更新变量 cs.

THREAD-1:    current.fetch_add(1);
THREAD-2:    cs = current;
THREAD-1:    if(current>=4){ current=0; }

如您所见,cs 在电流为 4 时获得它的值。

此外,这不是 objective-c 问题,这只是 C++ 问题。