Допустимо ли вложить критический раздел?

Например, будет ли это действительным?

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

Очевидно, я бы никогда не сделал это намеренно, но что, если это произойдет в результате вызовов функций, так что будет вызван "первый уровень" для блокировки объекта для сложного (например, поиска) алгоритма и "второго уровня" вызывается в функциях доступа этого объекта?

3 ответа

Решение

Да, это действительно, чтобы войти в тот же критический раздел, когда он уже находится внутри. Из документов:

После того как поток владеет критическим разделом, он может выполнить дополнительные вызовы EnterCriticalSection или TryEnterCriticalSection, не блокируя его выполнение. Это предотвращает взаимную блокировку потока при ожидании критического раздела, которым он уже владеет. Поток входит в критическую секцию каждый раз, когда EnterCriticalSection и TryEnterCriticalSection завершаются успешно. Поток должен вызывать LeaveCriticalSection один раз для каждого входа в критическую секцию.

Из документации:

После того как поток владеет критическим разделом, он может выполнить дополнительные вызовы EnterCriticalSection или TryEnterCriticalSection, не блокируя его выполнение. Это предотвращает взаимную блокировку потока при ожидании критического раздела, которым он уже владеет. Поток входит в критическую секцию каждый раз, когда EnterCriticalSection и TryEnterCriticalSection завершаются успешно. Поток должен вызывать LeaveCriticalSection один раз для каждого входа в критическую секцию.

Для проверки двух других постов. Быстрый просмотр критического раздела в 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, что указывает на отсутствие потока, владеющего критическим разделом.

Другие вопросы по тегам