使用std :: atomic <T>的条件的基本用法

Sil*_*ler 7 c++ atomic c++11

所以我开始熟悉C++ 11 <atomic>类型.在过去,当我有一个原子标志时,我通常只是在访问它之前锁定一个互斥锁.一个常见的需求是检查标志是否false,如果是,则原子地将其设置为true然后执行某些操作.所以基本上这将是这样完成的,其中flag一个很简单bool:

{
    std::lock_guard<std::mutex> lock(my_mutex);
    if (!flag) 
    {
        flag = true;
        // do something;
    }
}
Run Code Online (Sandbox Code Playgroud)

所以,现在我想弄清楚如何实现同样的目标<atomic>.该文档说,赋值运算符和operator T原子类型是一个基本操作.但是,如果我换flagstd::atomic<bool>,我想我不能简单地说:

if (!flag)
{
  flag = true;
  // do something
}
Run Code Online (Sandbox Code Playgroud)

...因为即使表达式(!flag)是原子的,并且赋值flag = true是原子的,也没有什么可以防止另一个线程在这两个语句之间修改标志.

所以,如果我理解正确的话在这里,唯一的正确使用- 在所有 -用原子类型,条件,其中条件可以修改原子变量的结果,是使用比较和交换操作?我对么?

所以,我不得不说:

bool expected = false;
if (flag.compare_exchange_weak(expected, true))
{
   // do something
}
Run Code Online (Sandbox Code Playgroud)

我的理解是正确的吗?

Bar*_*rry 5

如果有多个运行相同代码的线程需要进行翻转,是的-您将需要使用compare_exchange_weak()compare_exchange_strong()正是出于您建议的原因(可能更喜欢强)。

但是,并不是说这是原子条件条件的唯一正确用法。例如,如果我有一个仅读取原子的线程和一个写入原子的线程,那么以简单的方式使用它们是完全合理的...例如:

std::atomic<bool> done{false};

// thread 1
while (!done) {
    ....
}

// thread 2
stop() { done = true; }
Run Code Online (Sandbox Code Playgroud)

没有理由让我在done.compare_exchange_strong(expected, true)那里做。太过分了。确实是视情况而定。