Подтвердить что ты не робот

Правильно ли вставить критический раздел?

Например, допустимо ли это?

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

Ответ 3

Чтобы проверить другие два сообщения. Быстрый просмотр критического раздела в WinDbg показывает, что критикальный раздел поддерживает целочисленную переменную для хранения значений Recursion.

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, что указывает на отсутствие потока, критический раздел.