Код, помещенный между ::EnterCriticalSection() и
::LeaveCriticalSection() с одной и той же критической секцией в качестве
параметра, никогда не будет выполняться параллельно. Это означает, что если
нить №1 успела "захватить" критическую секцию m_lockObject, то при
попытке нити №2 заполучить эту же критическую секцию в свое единоличное
пользование, ее выполнение будет приостановлено до тех пор, пока нить №1 не
"отпустит" m_lockObject при помощи вызова ::LeaveCriticalSection(). И
наоборот, если нить №2 успела раньше нити №1, то та "подождет", прежде чем начнет работу с m_pObject.
Работа с критическими секциями
Что же происходит внутри критических секций и как они
устроены? Прежде всего, следует отметить, что критические секции – это не
объекты ядра операционной системы. Практически вся работа с критическими
секциями происходит в создавшем их процессе. Из этого следует, что критические
секции могут быть использованы только для синхронизации в пределах одного
процесса. Теперь рассмотрим критические секции поближе.
Структура RTL_CRITICAL_SECTION
typedef struct _RTL_CRITICAL_SECTION {
PRTL_CRITICAL_SECTION_DEBUG
DebugInfo; // Используется операционной системой
LONG LockCount; // Счетчик использования этой
критической секции
LONG RecursionCount; // Счетчик повторного захвата из
нити-владельца
HANDLE OwningThread; // Уникальный ID нити-владельца
HANDLE LockSemaphore; // Объект ядра используемый для ожидания
ULONG_PTR SpinCount; // Количество холостых циклов перед
вызовом ядра
} RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION;
|
Поле LockCount увеличивается на единицу при каждом
вызове ::EnterCriticalSection() и уменьшается при каждом вызове
::LeaveCriticalSection(). Это первая (а часто и единственная проверка) на пути
к "захвату" критической секции. Если после увеличения в этом поле
находится ноль, это означает, что до этого момента непарных вызовов ::EnterCriticalSection()
из других ниток не было. В этом случае можно забрать данные, охраняемые этой
критической секцией в монопольное пользование. Таким образом, если критическая
секция интенсивно используется не более чем одной нитью, ::EnterCriticalSection() практически вырождается в ++LockCount, а
::LeaveCriticalSection() в --LockCount. Это очень важно. Это означает, что
использование многих тысяч критических секций в одном процессе не повлечет
значительного расхода ни системных ресурсов, ни процессорного времени.
СОВЕТ
Не стоит экономить на критических
секциях. Много cэкономить все равно не получится.
|
В поле RecursionCount хранится количество повторных
вызовов ::EnterCriticalSection() из одной и той же нити. Действительно, если
вызвать ::EnterCriticalSection() из одной и той же нити несколько раз, все
вызовы будут успешны. Т.е. вот такой код не остановится навечно во втором
вызове ::EnterCriticalSection(), а отработает до конца.
Рекомендуем скачать другие рефераты по теме: реферат на экономическую тему, инновационная деятельность.
Предыдущая страница реферата |
1
2
3
4
5
6
7
8
9
10
11 |
Следующая страница реферата