Поделиться через


Объекты критического раздела

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

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

Начиная с Windows Server 2003 с пакетом обновления 1 (SP1) потоки, ожидающие критического раздела, не получают критический раздел в порядке очереди. Это изменение значительно повышает производительность для большинства кода. Однако некоторые приложения зависят от упорядочения "первым в систему" (FIFO) и могут работать плохо или вообще не работать в текущих версиях Windows (например, приложения, которые использовали критические разделы в качестве средства ограничения скорости). Чтобы обеспечить правильную работу кода, может потребоваться добавить дополнительный уровень синхронизации. Например, предположим, что у вас есть поток производителя и поток потребителя, которые используют объект критического раздела для синхронизации своей работы. Создайте два объекта событий, по одному для каждого потока, чтобы сообщить о готовности другого потока к продолжению. Поток-получатель будет ожидать, пока производитель сообщит о своем событии перед входом в критический раздел, а поток-производитель будет ожидать, пока поток потребителя сообщит о своем событии, прежде чем входить в критический раздел. После того как каждый поток покидает критический раздел, он сообщает о своем событии, чтобы освободить другой поток.

Windows Server 2003 и Windows XP: Потоки, ожидающие критического раздела, добавляются в очередь ожидания; Они просыпаются и обычно получают критически важный раздел в том порядке, в котором они были добавлены в очередь. Однако если потоки добавляются в эту очередь с достаточной скоростью, производительность может снизиться из-за времени, необходимого для пробуждения каждого ожидающего потока.

Этот процесс отвечает за выделение памяти, используемой критическим разделом. Как правило, это делается путем простого объявления переменной типа CRITICAL_SECTION. Прежде чем потоки процесса смогут использовать его, инициализируйте критический раздел с помощью функции InitializeCriticalSection или InitializeCriticalSectionAndSpinCount .

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

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

Поток использует функцию InitializeCriticalSectionAndSpinCount или SetCriticalSectionSpinCount для указания счетчика спина для объекта критического раздела. Вращение означает, что при попытке получить критический раздел, который заблокирован, поток переходит в цикл, проверяет, снята ли блокировка, и если блокировка не снята, поток переходит в спящий режим. В однопроцессорных системах счетчик спинов игнорируется, а для критического числа спинов секций задано значение 0 (ноль). В многопроцессорных системах, если критический раздел недоступен, вызывающий поток запускает dwSpinCount перед выполнением операции ожидания в семафоре, связанном с критическим разделом. Если критический раздел становится свободным во время операции вращения, вызывающий поток избегает операции ожидания.

Любой поток процесса может использовать функцию DeleteCriticalSection для освобождения системных ресурсов, выделенных при инициализации объекта критического раздела. После вызова этой функции объект критического раздела нельзя использовать для синхронизации.

Когда принадлежит объект критического раздела, единственными другими затронутыми потоками являются потоки, ожидающие владения в вызове EnterCriticalSection. Потоки, которые не ожидают, могут продолжать работать бесплатно.

Объекты мьютексов

Использование объектов критического раздела