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

明らかに、私は意図的にこれを行うことはありませんが、複雑な(検索などの)アルゴリズムのオブジェクトをロックするために「第1レベル」が呼び出され、「第2レベル」が呼び出されるような関数呼び出しの結果としてこれが発生した場合はどうなりますか?そのオブジェクトのアクセサ関数で呼び出されますか?

4

3 に答える 3

37

はい、すでにその中にいる間に同じクリティカルセクションに入るのは有効です。ドキュメントから:

スレッドがクリティカルセクションの所有権を取得した後、その実行をブロックすることなく、EnterCriticalSectionまたはTryEnterCriticalSectionへの追加の呼び出しを行うことができます。これにより、スレッドがすでに所有しているクリティカルセクションを待機しているときに、スレッドがデッドロックするのを防ぎます。EnterCriticalSectionとTryEnterCriticalSectionが成功するたびに、スレッドはクリティカルセクションに入ります。スレッドは、クリティカルセクションに入るたびにLeaveCriticalSectionを1回呼び出す必要があります。

于 2011-08-31T16:44:17.790 に答える
11

ドキュメントから:

スレッドがクリティカルセクションの所有権を取得した後、その実行をブロックすることなく、EnterCriticalSectionまたはTryEnterCriticalSectionへの追加の呼び出しを行うことができます。これにより、スレッドがすでに所有しているクリティカルセクションを待機しているときに、スレッドがデッドロックするのを防ぎます。EnterCriticalSectionとTryEnterCriticalSectionが成功するたびに、スレッドはクリティカルセクションに入ります。スレッドは、クリティカルセクションに入るたびにLeaveCriticalSectionを1回呼び出す必要があります。

于 2011-08-31T16:44:22.383 に答える
2

他の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 に答える