C++ 条件变量详解:notify_one()、notify_all() 与 wait() 原理和优化
C++ 条件变量详解:notify_one()、notify_all() 与 wait() 原理和优化
本文深入探讨 C++ 条件变量的核心机制,包括 notify_one()、notify_all() 以及 wait()、wait_for()、wait_until() 的运作方式。
原子操作顺序
notify_one() 和 notify_all(),以及 wait()/wait_for()/wait_until() 的三个原子部分(解锁+等待、唤醒和加锁)的效应遵循一个单一总顺序,类似于对原子变量的修改顺序。这个顺序特定于每个条件变量,保证了操作的原子性和一致性。
举例来说,notify_one() 无法延迟并解除一个在调用 notify_one() 之后才开始等待的线程。
避免'赶紧等待'场景
通知线程并不强制要求持有与等待线程相同的互斥锁。实际上,这样做反而会降低效率,因为被通知的线程会立即再次阻塞,等待通知线程释放锁,形成'赶紧等待'的窘境。
值得庆幸的是,一些实现(例如许多 pthread 实现)能够识别这种情况,并进行优化:在通知调用中,直接将等待线程从条件变量的队列转移到互斥锁的队列,而无需唤醒该线程,从而避免了不必要的上下文切换。
持锁通知的必要性
尽管存在优化,但在某些情况下,我们仍然需要在持有锁的情况下进行通知操作。例如:
- 当程序需要精确的事件调度时。* 当等待线程在条件满足时会退出程序,导致通知线程的条件变量被销毁时。
在上述情况下,如果在解锁互斥锁之后但在通知之前发生虚假唤醒,会导致在已销毁的对象上调用 notify,引发程序崩溃。
总结
本文详细介绍了 C++ 条件变量的内部工作原理、常见优化以及潜在的陷阱。理解这些内容对于编写高效、可靠的多线程程序至关重要。
原文地址: https://www.cveoy.top/t/topic/jPy 著作权归作者所有。请勿转载和采集!