在多线程C ++应用程序中,我是否需要一个互斥锁来保护一个简单的布尔值?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在多线程C ++应用程序中,我是否需要一个互斥锁来保护一个简单的布尔值?相关的知识,希望对你有一定的参考价值。

我有一个多线程C ++应用程序,它使用OpenSceneGraph库进行3D渲染。我打算使用boost :: threads将OSG的渲染循环作为一个单独的线程,将包含共享状态的数据结构传递给线程。我试图避免任何太重量级(如互斥量)的同步,因为渲染循环需要非常紧,OSG本身试图避免必须锁定。大多数共享状态在线程启动之前设置,并且从不更改。我确实有一些需要更改的数据,我计划双重缓冲。但是,我有一个简单的布尔值来表示线程暂停渲染,然后恢复渲染,另一个杀死它。在这两种情况下,app线程都会设置bool,而渲染线程只会读取它。我是否需要同步访问这些bool?据我所知,可能发生的最糟糕的事情是渲染循环在暂停或退出之前继续进行额外的帧。

答案

在C ++ 11及更高版本中,它具有标准定义的并发性,为此目的使用std::atomic<bool>。来自http://en.cppreference.com/w/cpp/atomic/atomic

如果一个线程写入原子对象而另一个线程从中读取,则行为是明确定义的(有关数据争用的详细信息,请参阅内存模型)。


在过去的某些时候,对于某些编译器和某些操作环境,以下旧答案可能都是正确的,但今天不应该依赖它:

你没错,在这种情况下你不需要同步bool。你应该声明它们volatile,以确保编译器每次实际从内存中读取它们,而不是在线程中缓存先前的读取(这是一个简化的解释,但它应该为此目的)。

以下问题有关于此的更多信息: C++ Thread, shared data

另一答案

为什么不简单地使用interlocked variable

另一答案

至于C ++ 11及更高版本,它最终是线程感知的,并明确指出在一个线程中修改bool(或其他非原子变量)并在另一个线程中同时访问它是未定义的行为。在你的情况下,使用std::atomic<bool>应该足以使你的程序正确,从而避免使用锁。 不要使用volatile。它与线程无关。有关更多讨论,请查看Can I read a bool variable in a thread without mutex?

另一答案

我不认为你需要一个完全成熟的互斥锁 - 尽管如果你没有使用支持wait原语的同步对象,渲染线程将需要忙于等待'挂起'状态。

您应该考虑使用各种互锁交换原语(Windows下的InterlockedExchange)。不是因为来自bool的读/写是非原子的,而是为了确保没有奇怪的行为,编译器在单个线程上重新排序内存访问。

另一答案

这个主题有关于线程安全的更多信息和讨论,特别是对于简单的数据类型:

How can I create a thread-safe singleton pattern in Windows?

以上是关于在多线程C ++应用程序中,我是否需要一个互斥锁来保护一个简单的布尔值?的主要内容,如果未能解决你的问题,请参考以下文章

使用互斥锁后程序仍然崩溃(我可以在同一个线程中使用互斥锁吗?)

我需要在 Swift 中 memset 一个 C 结构吗?

如何使用互斥锁在 C 中执行生产者-消费者程序

在多线程 Java 程序中,每个线程是不是都有自己的 System.out 副本?

在多线程 C++11 程序中未处理异常时会发生啥?

在多线程 C++11 程序中未处理异常时会发生啥?