是否可以使用atomic <bool>进行多线程同步而不是事件</bool>

时间:2014-02-20 02:49:50

标签: windows multithreading events c++11 atomic

与在C ++ 11中一样,它已被导入原子,正如您在旧代码中所知,它使用Windows事件(CreateEvent / SetEvent)进行线程同步。伪代码如下。

主题A:

while(true)
{
    if(check event is set)
       break;
    else
       do stuff
}

主题B:

SetEvent() //ask thread A stop.

我想知道是否在这种情况下。是否可以使用原子,如下所示更简单,有什么原子bool不能取代事件?提前谢谢!

std::atomic<bool> bFlag = false;

主题A:

while(true)
{
    if(bFlag)
       break;
    else
       do stuff
}

主题B:

bFlag = true;

[更新]

为了使问题更清楚,线程A不会写入bFlag,它只是读取它以了解何时退出线程。线程B将写入bFlag以通知线程A停止。

解决方案中没有性能考虑因素。

1 个答案:

答案 0 :(得分:1)

这样做可能是精心设计的解决方案的一部分。你需要注意不太明显的竞争条件和ABA问题(如果“做东西”使用bFlag)。

在下面我说“坏”时我的意思是“两个线程可以同时读/写或写/写同一个数据吗?”。

如果在bFlag设置为true后“do stuff”开始执行仅几纳秒,那会不会很糟糕? 什么条件可能导致bFlag再次变错?
如果在bFlag变为假之后“做东西”没有在几纳秒内运行,那会不会很糟糕? 如果程序在bFlag设置为false之前多次运行“do stuff”,那会不好?

如果你能正确回答这些问题,没有技术上的理由你不能这样做,但这可能是一条简单的途径。

在大多数情况下,std :: atomic是使用原子比较和交换(CAS)(http://en.wikipedia.org/wiki/Compare-and-swap)CPU指令实现的,而MESI协议(http://en.wikipedia.org/wiki/MESI_protocol)将确保缓存一致性。我不认为有任何阻止这种情况可以通过操作系统级别的互斥体来实现。如果这不是性能瓶颈或性能不是主要问题,那么使用bFlag周围的互斥量和“做东西”可能会更容易。

另一种可能的途径是使用std :: futures来从线程B异步“执行操作”。使用它可以将“do stuff”视为自己的函数,而不必担心线程的血腥细节。 (http://en.cppreference.com/w/cpp/thread/future

**编辑** 我不知道你的意思是一个特定于Windows的事件。我的答案仍然适用于他的一般情况,但由于我不知道Windows SetEvent的细节,它的语义可能会改变任何东西。