多年来,Windows中关键部分的实现已经发生了变化,但它一直是用户模式和内核调用的结合。
CRITICAL_SECTION是一个包含用户模式更新值,内核模式对象的句柄-EVENT或类似的东西以及调试信息的结构。
EnterCriticalSection使用互锁的测试和设置操作来获取锁。如果成功,这就是所需要的(几乎它也会更新所有者线程)。如果set-and-set操作失败,则使用更长的路径,这通常需要等待WaitForSignleObject
的内核对象。如果用InitializeCriticalSectionAndSpinCount
进行初始化,则EnterCriticalSection
可能会旋转重试以在用户模式下使用互锁操作进行采集。
下面是EnterCriticialSection
“快” /无竞争的路径在Windows 7(64位)与一些意见直列
0:000> u rtlentercriticalsection rtlentercriticalsection+35
ntdll!RtlEnterCriticalSection:
00000000`77ae2fc0 fff3 push rbx
00000000`77ae2fc2 4883ec20 sub rsp,20h
; RCX points to the critical section rcx+8 is the LockCount
00000000`77ae2fc6 f00fba710800 lock btr dword ptr [rcx+8],0
00000000`77ae2fcc 488bd9 mov rbx,rcx
00000000`77ae2fcf 0f83e9b1ffff jae ntdll!RtlEnterCriticalSection+0x31 (00000000`77ade1be)
; got the critical section - update the owner thread and recursion count
00000000`77ae2fd5 65488b042530000000 mov rax,qword ptr gs:[30h]
00000000`77ae2fde 488b4848 mov rcx,qword ptr [rax+48h]
00000000`77ae2fe2 c7430c01000000 mov dword ptr [rbx+0Ch],1
00000000`77ae2fe9 33c0 xor eax,eax
00000000`77ae2feb 48894b10 mov qword ptr [rbx+10h],rcx
00000000`77ae2fef 4883c420 add rsp,20h
00000000`77ae2ff3 5b pop rbx
00000000`77ae2ff4 c3 ret
因此,底线是,如果线程并不需要一个diassembly阻止它不会使用系统调用,只是互锁的测试和设置操作。如果需要阻止,则会有系统调用。释放路径也使用互锁测试和设置,并且如果其他线程被阻塞,可能需要系统调用。
比较这对互斥总是需要一个系统调用NtWaitForSingleObject
和NtReleaseMutant
互斥使用'CreateMutex'。 – Mehrdad 2011-03-03 03:01:06
自旋锁实际上是用于内核使用的(当然,您可以在自己的程序中不做任何事情,但这没有帮助)。以下关于自旋锁的答案以前是误导性的,但现在海报已经纠正了它。 – casablanca 2011-03-03 03:28:51
抱歉有关混淆。 – 0xC0000022L 2011-03-03 03:35:19