互斥体真的慢了吗?

Adr*_*son 19 windows multithreading mutex

我已经阅读了很多次,无论是在网络上还是网络上,互斥体都比关键部分/信号量/插入你的首选同步方法慢.但我从未见过任何论文或研究或其他什么来支持这一主张.

那么,这个想法来自哪里?这是神话还是现实?互斥体真的慢吗?

Mic*_*ick 18

在Jim Beveridge和Robert Wiener的"win32中的多线程应用程序"一书中,它说:"锁定无主的互斥锁需要的时间比锁定无关的关键部分要长近100倍,因为关键部分可以在没有用户模式下完成涉及内核"

在msdn上,它说"关键部分对象提供了一种更快,更有效的互斥同步机制"

  • 在Java中,它都很慢;-) (23认同)
  • @Benj - 由于临界区不是内核对象,因此它只能在单个进程中运行.如果需要跨多个进程同步访问,则可以选择互斥. (5认同)

Spe*_*nce 15

我不相信任何答案都会触及他们为什么不同的关键点.

互斥锁处于操作系统级别.存在一个已命名的互斥锁,可以从操作系统中的任何进程访问(前提是其ACL允许从所有进程访问).

关键的部分是更快它们不需要系统调用到内核模式,但他们只会工作WITHIN一个过程,你可以使用一个关键部分锁定超过一个过程.因此,根据您要实现的目标以及软件设计的外观,您应该选择最合适的工具.

我还要向你指出,信号量与互斥/关键部分是分开的,因为它们的数量.信号量可用于控制对资源的多个并发访问,其中正在访问或未访问互斥/临界区.


Chr*_*her 5

CRITICAL_SECTION实现为具有上限旋转计数的自旋锁.有关此信息,请参阅MSDN InitializeCriticalSectionAndSpinCount.

当旋转计数'过去'时,临界区锁定一个信号量(或者它实现的任何内核锁).

所以在代码中它的工作原理是这样的(不是真的有效,应该只是一个例子):

CRITICAL_SECTION s;

void EnterCriticalSection( CRITICAL_SECTION* s )
{
    int spin_count = s.max_count;
    while( --spin_count >= 0 )
    {
        if( InterlockedExchange( &s->Locked, 1 ) == 1 )
        {
           // we own the lock now
           s->OwningThread = GetCurrentThread();
           return;
        }
    }
    // lock the mutex and wait for an unlock
    WaitForSingleObject( &s->KernelLock, INFINITE );
}
Run Code Online (Sandbox Code Playgroud)

因此,如果您的关键部分只保持很短的时间,并且进入的线程只等待很少的"旋转"(周期),那么关键部分可以非常有效.但如果不是这种情况,那么关键部分会浪费许多循环,什么都不做,然后又回退到内核同步对象.

所以权衡是:

Mutex:缓慢获取/释放,但长期"锁定区域"没有浪费周期

CRITICAL_SECTION:快速获取/释放无主区域,但浪费了自有区域的周期.