std::atomic 变量上的分支是否可能是错误来源?

问题描述 投票:0回答:1

我听说在

if
上使用
switch
std::atomic
是错误的来源,因为一些与内存排序有关的参数

具体来说,代码如下:


void secondThreadFunc() {
  puts( "Starting 2nd thread" );
  branchVar = true;
}

int main() {

  std::thread t( secondThreadFunc );
  Sleep( 100 );
  
  // Branching on a std::atomic considered dangerous due to memory ordering issues?
  if( branchVar ) {
    puts( "Branch true" );
  }
  else {
    puts( "Branch false" );
  }

  t.join();
}


if( branchVar )
调用中植入竞争条件,被认为是不安全的编程。应始终使用
std::mutex
来锁定分支变量的访问

这是真的吗?有人可以向我解释为什么会这样吗?内存排序会导致

std::atomic
分支引发竞争条件吗?

multithreading thread-safety stdatomic
1个回答
0
投票

在原子变量上进行分支没有任何问题。

通常有一个循环读取原子变量,如果读取为某个值则退出。这就是所谓的“旋转”。自旋基本上是原子变量上的向后分支。 自旋常用于同步原语的实现中,包括

std::mutex

std::call_once
。 (您可能无法直接在 STL 实现中看到它,因为这通常是在较低级别中完成的)。
当直接在

if

switch
表达式中使用原子变量时,会发生隐式转换,相当于不带参数的
.load()
,并且内存顺序隐式为
memory_order_seq_cst
。这是最安全的内存顺序,因此不会引入任何新问题。原子的使用可能仍然存在问题,因为可能会与其他数据发生数据竞争,但这取决于您的代码,与原子本身没有任何关系。

使用
std::mutex

等的建议可能来自这样的事实:

std::atomic
本身仅为其自身提供原子性。因此,如果您在线程中修改原子数据和其他一些数据,然后在原子上进行分支,则可能会出现与其他数据修改相关的数据争用。或者,如果一切都正确的话,可能不会出现数据竞争。
    

© www.soinside.com 2019 - 2024. All rights reserved.