Допустимо ли вложить критический раздел? - PullRequest
15 голосов
/ 31 августа 2011

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

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 ]

29 голосов
/ 31 августа 2011

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

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

10 голосов
/ 31 августа 2011

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

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

1 голос
/ 09 августа 2013

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

...