在多线程 C++ app,我需要一个互斥体来保护一个简单的布尔值吗?
我有一个多线程 C++ 应用程序,它使用 OpenSceneGraph 库进行 3D 渲染。 我计划使用 boost::threads 将 OSG 的渲染循环作为单独的线程启动,将包含共享状态的数据结构传递到线程中。 我试图避免任何过于重量级的同步(如互斥体),因为渲染循环需要非常紧密,并且 OSG 本身试图避免必须锁定。 大多数共享状态是在线程启动之前设置的,并且从未改变。 我确实有一些数据确实需要更改,我计划对其进行双缓冲。 但是,我有一个简单的布尔值用于向线程发出信号以暂停渲染,然后恢复渲染,然后用另一个布尔值来终止它。 在这两种情况下,应用程序线程都会设置布尔值,而渲染线程只会读取它。 我需要同步对这些布尔值的访问吗? 据我所知,可能发生的最糟糕的事情是渲染循环在挂起或退出之前继续运行额外的帧。
I have a multi-threaded C++ app which does 3D rendering with the OpenSceneGraph library. I'm planning to kick off OSG's render loop as a separate thread using boost::threads, passing a data structure containing shared state in to the thread. I'm trying to avoid anything too heavyweight (like mutexes) for synchronization, as the render loop needs to be pretty tight, and OSG itself tries to avoid having to ever lock. Most of the shared state is set before the thread is started, and never changed. I do have some data that does need to be changed, which I am planning to double-buffer. However, I have a simple boolean for signaling the thread to suspend rendering, and later resume rendering, and another to kill it. In both cases the app thread sets the bool, and the render thread only reads it. Do I need to synchronize access to these bools? As far as I can tell, the worse thing that could happen is the the render loop continues on for an extra frame before suspending or quitting.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
在具有标准定义并发性的 C++11 及更高版本中,请使用
std::atomic
来实现此目的。 来自 http://en.cppreference.com/w/cpp/atomic/atomic:以下旧答案在过去的某个时间对于某些编译器和某些操作环境可能是正确的,但今天不应该依赖它:
你是对的,在这种情况下,你不需要同步布尔值。 不过,您应该将它们声明为 易失性 ,以确保编译器每次实际上都从内存中读取它们,而不是在线程中缓存先前的读取(这是一个简化的解释,但它应该用于此目的) .以下问题提供了有关此问题的更多信息:
C++线程,共享数据
In C++11 and later, which has standards-defined concurrency, use
std::atomic<bool>
for this purpose. From http://en.cppreference.com/w/cpp/atomic/atomic:The following old answer may have been true at some time in the past with some compilers and some operating environments, but it should not be relied upon today:
You're right, in this case you won't need to synchronise the bools. You should declare themvolatile
though, to ensure that the compiler actually reads them from memory each time, instead of caching the previous read in a thread (that's a simplified explanation, but it should do for this purpose).The following question has more information about this:
C++ Thread, shared data
为什么不简单地使用互锁变量?
Why not simply use an interlocked variable?
至于 C++11 及更高版本,它最终是线程感知的,并明确指出在一个线程中修改 bool (或其他非原子变量)并同时在另一个线程中访问它是未定义的行为。
在您的情况下,使用
std::atomic
应该足以使您的程序正确,从而避免使用锁。不要使用
易失性
。 它与线程无关。有关更多讨论,请参阅我可以读取布尔值吗线程中的变量没有互斥锁?
As for C++11 and later it is finally threads-aware and clearly states that modifying a bool (or other non-atomic variable) in one thread and accessing it at the same time in another one is undefined behavior.
In you case using
std::atomic<bool>
should be enough to make your program correct, saving you from using locks.Do not use
volatile
. It has nothing to do with threads.For more discussion look at Can I read a bool variable in a thread without mutex?
我认为您在这里需要一个完全成熟的互斥体 - 尽管如果您不使用支持等待原语的同步对象,渲染线程将需要在“挂起”状态下忙于等待。
不过,您应该考虑使用各种互锁交换原语(Windows 下的 InterlockedExchange)。 并不是因为布尔值的读/写是非原子的,而是为了确保编译器在单个线程上重新排序内存访问时不会出现奇怪的行为。
I don't think you need a fully fledged mutex here -- though the render thread will need to busy wait in the 'suspended' state if you aren't using a synchronization object that supports a wait primitive.
You should look into using the various interlocked exchange primitives though (InterlockedExchange under Windows). Not because read/writes from the bool are non-atomic, but to ensure that there are no weird behaviours the compiler reordering memory accesses on a single thread.
该线程有更多关于线程安全的信息和讨论,特别是对于简单的数据类型:
如何在 Windows 中创建线程安全的单例模式?
This thread has a little more info and discussion on thread-safety, especially for simple data types:
How can I create a thread-safe singleton pattern in Windows?