Реферат: Критические секции

m_pObject = pNewobject;

::LeaveCriticalSection(&m_lockObject);

}

Код, помещенный между ::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

void Proc1()

{

::EnterCriticalSection(&m_lock);

//. ..

Proc2()

//. ..

::LeaveCriticalSection(&m_lock);

}

// Всеещенить №1

К-во Просмотров: 759
Бесплатно скачать Реферат: Критические секции