为什么std::mutex的速度比CRITICAL_SECTION慢两倍

8

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会错过什么?
另外,为什么他们称它为Mutex,而它并没有用Mutex来实现?

4
你在计时什么?创建互斥量、锁定它、解锁它等吗?与Win32互斥量的区别在于:Win32互斥量是跨进程的,而标准只要求跨线程的互斥量,这可以是一种更轻量级的构造(Windows使用临界区实现)。 - Jerry Coffin
1
CMutex是使用互斥锁实现的,它并不便宜。std::mutex是建立在并发运行时之上的,它是相当庞大的代码块,具有显著扩展操作系统提供的线程和调度原语的功能。层叠是沉重的,这并不是免费的。如果critsect适合您的目的,并且开销确实很重要,那么只需推迟问题并使用它即可。 - Hans Passant
1
我只是在计时锁定/解锁。我只是好奇std::mutex除了临界区之外还做了什么。如果它有用,那我不应该想要它吗?如果它没有用,为什么还会这样做?我认为我会使用std::mutex,但我只是想知道它额外做了什么。 - Philip
1
@Philip:实际上唯一的优点是:可移植性,以及它出现在其他C++线程函数的签名中。 - Ben Voigt
1
它似乎被整合到一个更广泛的功能集中,例如,代码路径超过了超时选项,它似乎在实现自己的调度器,有一个锁队列等等。如果只使用简单的互斥锁,是否所有这些都提供任何好处对我来说还不清楚。 - Harry Johnston
显示剩余2条评论
1个回答

2

std::mutex提供了非递归的所有权语义。CRITICAL_SECTION提供了递归语义。因此,我认为std::mutex实现中的额外层次(至少部分地)是为了解决这种差异。

更新:通过代码调试,看起来std::mutex是通过队列和InterlockedX指令实现的,而不是经典的Win32 CRITICAL_SECTION。尽管std::mutex是非递归的,但RTL中的底层代码可以选择处理递归锁甚至定时锁。


这个听起来很合理,但在我的测试中,std::recursive_mutex并不比std::mutex快。这表明它们都在做一些减速的事情,而这与它们是否递归无关,对吗? - Philip
6
由于尝试递归锁定std::mutex是未定义行为,因此我不明白为什么需要编写代码来“解决差异”。 - T.C.
也许这是用来检测未定义行为的调试代码?定时是使用发布版还是调试版完成的? - Adrian McCarthy
这不是一个有效的理由,因为递归互斥锁满足常规互斥锁的所有语义,因此不需要额外的代码来解决差异。 - rdb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接