【问题标题】:Why is std::mutex twice as slow as CRITICAL_SECTION为什么 std::mutex 比 CRITICAL_SECTION 慢两倍
【发布时间】:2015-04-18 09:28:14
【问题描述】:

std::mutex 是通过临界区实现的,这就是它比 OS Mutex(在 Windows 上)快得多的原因。但是它不如 Windows CRITICAL_SECTION 快。

时间只是一个线程中的一个紧密循环:

423.76ns ATL CMutex
 41.74ns std::mutex
 16.61ns win32 Critical Section

我的问题是 std::mutex 还在做什么?我查看了来源,但无法遵循它。然而,在它遵循 Crit Sec 之前还有一些额外的步骤。我的问题是:这些额外的步骤是否有用?也就是说,额外的步骤是什么;使用 CRITICAL_SECTION 会错过什么?

如果它不是用互斥锁实现的,为什么他们称它为互斥锁?

【问题讨论】:

  • 你在计时什么?创建互斥体,锁定它,解锁它,......?至于与 Win32 互斥锁的区别:Win32 互斥锁是跨进程互斥锁。该标准只需要一个跨线程互斥体,它可以是一个更轻量级的结构(并且 Windows 实现了一个临界区)。
  • CMutex 是用互斥锁实现的,它并不便宜。 std::mutex 构建在并发运行时之上,它是一大块代码,其功能大大超出了操作系统提供的线程和调度原语。分层很重,这不是免费的。如果 critsect 符合您的目的并且开销确实很重要,那么只需解决问题并使用它。
  • 我正在计时只是锁定/解锁。我只是好奇 std::mutex 在暴击秒之外做了什么。如果它有用,那么我不应该想要它吗?如果它没有用,为什么要这样做?我想我会使用 std::mutex 但我只是想知道它有什么额外的作用。
  • @Philip:真正唯一的优点是:可移植性,并且它出现在其他 C++ 线程函数的签名中。
  • 它似乎被集成到更广泛的功能集中,例如,代码路径通过超时选项,它似乎正在实现自己的调度程序,具有锁定队列等。如果我不清楚您使用的只是简单的互斥锁,这将提供任何好处。

标签: c++ winapi c++11 mutex critical-section


【解决方案1】:

std::mutex 提供非递归所有权语义。 CRITICAL_SECTION 提供递归语义。所以我假设 std::mutex 实现中的额外层(至少部分)解决了这种差异。

更新:单步执行代码,看起来 std::mutex 是根据队列和 InterlockedX 指令实现的,而不是经典的 Win32 CRITICAL_SECTION。即使 std::mutex 是非递归的,RTL 中的底层代码也可以选择处理递归甚至定时锁。

【讨论】:

  • 这听起来很合理,只是在我的测试中 std::recusive_mutex 并不比 std::mutex 快。这表明它们都在做一些事情来减慢它们的速度,这与它们是否递归无关,对吧?
  • 由于尝试递归锁定 std::mutex 是 UB,我不明白为什么需要代码来“解决差异”。
  • 也许是检测UB的调试代码?计时是使用发布还是调试完成的?
  • 这不是一个正当理由,因为递归互斥锁满足常规互斥锁的所有语义,因此不需要额外的代码来解决差异。
猜你喜欢
  • 2012-04-17
  • 1970-01-01
  • 1970-01-01
  • 2022-09-28
  • 1970-01-01
  • 2017-03-28
  • 2015-02-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多