例如,这是否有效?
CRITICAL_SECTION cs;
::InitializeCriticalSection( &cs );
::EnterCriticalSection( &cs ); // First level
::EnterCriticalSection( &cs ); // Second level
/* do some stuff */
::LeaveCriticalSection( &cs ); // Second level
::LeaveCriticalSection( &cs ); // First level
::DeleteCriticalSection( &cs );
显然,我绝不会故意这样做,但是如果这是由于函数调用而产生的,那么“第一级”被调用来锁定一个复杂(例如搜索)算法的对象和“第二级“在该对象的访问者函数中被调用?
答案 0 :(得分:29)
是的,在其内部输入相同的关键部分是有效的。来自the docs:
在线程拥有关键部分的所有权后,它就可以生成 对EnterCriticalSection或TryEnterCriticalSection的额外调用 没有阻止它的执行。这可以防止线程 在等待关键部分时它会自行死锁 已经拥有。线程每次都进入临界区 EnterCriticalSection和TryEnterCriticalSection成功。一个帖子 必须在每次进入时调用LeaveCriticalSection一次 关键部分。
答案 1 :(得分:10)
在线程拥有关键部分的所有权后,它可以对EnterCriticalSection或TryEnterCriticalSection进行额外调用,而不会阻止其执行。这可以防止线程在等待它已经拥有的关键部分时自行死锁。每次EnterCriticalSection和TryEnterCriticalSection成功时,线程都会进入临界区。每次进入临界区时,线程必须调用一次LeaveCriticalSection。
答案 2 :(得分:1)
验证其他两个帖子。快速查看WinDbg中的Critical部分显示cricital部分维护一个整数变量来保存递归计数。
0:001> dt RTL_CRITICAL_SECTION
+0x000 DebugInfo : Ptr32 _RTL_CRITICAL_SECTION_DEBUG
+0x004 LockCount : Int4B
+0x008 RecursionCount : Int4B
+0x00c OwningThread : Ptr32 Void
+0x010 LockSemaphore : Ptr32 Void
+0x014 SpinCount : Uint4B
RecursionCount - 线程可以多次获取关键部分。这个领域 表示同一线程获取临界区的次数。通过 默认情况下,该字段的值为0,表示没有线程拥有 关键部分。