为啥 boost::mutex 使用原子操作和事件而不是关键部分

Posted

技术标签:

【中文标题】为啥 boost::mutex 使用原子操作和事件而不是关键部分【英文标题】:Why boost::mutex uses atomic operations and events instead of critical sections为什么 boost::mutex 使用原子操作和事件而不是关键部分 【发布时间】:2015-11-03 11:44:22 【问题描述】:

根据this question 的答案boost::mutex 的最新版本使用原子操作和Win32 事件来阻塞等待而不是临界区。为什么?背后的原因是什么?

【问题讨论】:

我猜是为了增强便携性? @David Haim Win32 在您看来,与关键部分相比,Win32 事件不是特定于平台的东西? 我猜他们更喜欢平台事件+独立的原子操作而不是完全的平台实现 我怀疑你会在这里得到更好的答案,问开发人员在他们挂起的一些与提升相关的资源上做了这件事。这个问题仍然很有趣,因为将关键会话替换为事件看起来不太合理,除非 boost 旨在用于 ring0 代码。 @FrozenHeart 没有人说事件与平台无关。大卫说“增强可移植性”(图书馆)。该库将希望在所有操作系统上保证类似的语义。这可能是一个因素。不是我说“可能”,因为我不知道。所以,“增强可移植性”是关于boost::mutex行为而不是关于代码是否可以在平台上编译。 【参考方案1】:

我相信这就是您正在寻找的东西(来自https://www.justsoftwaresolutions.co.uk/articles/implementing_mutexes.html):

实现互斥锁的最简单方法是编写一个包装器 本机 Windows 同步对象之一的类;后 所有,这就是他们的目的。不幸的是,他们都有自己的 问题。 Mutex、Event 和 Semaphore 是内核对象,所以每个 同步调用需要到内核的上下文切换。这个可以 相当昂贵,尤其是在没有争用的情况下。

Boost 互斥锁仅设计用于在单个进程中使用,因此 CRITICAL_SECTION 看起来很吸引人。不幸的是,有 这也有问题。第一个是它需要 显式初始化,这意味着它不能可靠地用作 具有静态存储持续时间的对象的一部分 - 标准 静态初始化顺序问题是由潜在的 竞争条件,尤其是当互斥体用作本地静态时。在 大多数编译器,使用静态存储动态初始化对象 持续时间不是线程安全的,因此两个线程可能会竞相运行 初始化,可能导致初始化正在运行 两次,或一个线程在不等待初始化的情况下进行 正在由另一个线程运行来完成。第二个问题是 您不能在 CRITICAL_SECTION 上进行定时等待,这意味着我们需要 无论如何,另一个支持定时等待的互斥锁解决方案。

使用 CRITICAL_SECTIONs 作为 高性能互斥锁,这是一个线程解锁 CRITICAL_SECTION 会将所有权移交给等待线程。

【讨论】:

以上是关于为啥 boost::mutex 使用原子操作和事件而不是关键部分的主要内容,如果未能解决你的问题,请参考以下文章

如果足够多的活动,boost::mutex 可以锁定操作系统吗?

CUDA主机代码的互斥锁? boost::mutex 由于使用 nvcc 重新定义了 BOOST_COMPILER 没有解决方案

boost::interprocess_mutex 与进程本地 boost::mutex

boost::mutex::scoped_lock

/include/boost/thread/pthread/mutex.hpp:111: boost::mutex::~mutex(): Assertion `!res' 失败

使用 boost::mutex - 隐式删除错误(因为默认定义格式不正确)