20

例如,这是否有效?

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 );

显然,我永远不会故意这样做,但如果这是由于函数调用导致“第一级”被调用以锁定对象以用于复杂(例如搜索)算法和“第二级”怎么办?在该对象的访问器函数中被调用?

4

3 回答 3

37

是的,在已经进入相同的关键部分时输入相同的关键部分是有效的。从文档

在线程拥有临界区的所有权后,它可以对 EnterCriticalSection 或 TryEnterCriticalSection 进行额外调用,而不会阻止其执行。这可以防止线程在等待它已经拥有的临界区时自行死锁。每次 EnterCriticalSection 和 TryEnterCriticalSection 成功时线程进入临界区。线程每次进入临界区时都必须调用一次 LeaveCriticalSection。

于 2011-08-31T16:44:17.790 回答
11

文档中:

在线程拥有临界区的所有权后,它可以对 EnterCriticalSection 或 TryEnterCriticalSection 进行额外调用,而不会阻止其执行。这可以防止线程在等待它已经拥有的临界区时自行死锁。每次 EnterCriticalSection 和 TryEnterCriticalSection 成功时线程进入临界区。线程每次进入临界区时都必须调用一次 LeaveCriticalSection。

于 2011-08-31T16:44:22.383 回答
2

验证其他两个帖子。快速查看 WinDbg 中的关键部分可以看出,关键部分维护一个整数变量来保存递归计数。

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,表示没有线程拥有临界区。

于 2013-08-09T08:39:56.640 回答