Критические секции
Это самые простые объекты ядра Windows, которые не снижают общей эффективности приложения. Пометив блок кодов в качестве critical section, можно синхронизировать доступ к нему от нескольких потоков. Сначала следует объявить глобальную структуру:
CRITICAL_SECTION cs;
Затем инициализировать ее вызовом функции InitializeCriticalSection (&cs);. Обычно это делается один раз, перед тем как начнется работа с разделяемым ресурсом. Далее надо поместить охраняемую часть программы внутрь блока, который начинается вызовом функции EnterCriticalSection и заканчивается вызовом LeaveCriticalSection:
EnterCriticalSection (&cs); { //====== Здесь расположен охраняемый блок кодов } LeaveCriticalSection (Scs);
Функция EnterCriticalSection, анализируя поле структуры cs, которое является счетчиком ссылок, выясняет, вызвана ли она в первый раз. Если да, то функция увеличивает значение счетчика и разрешает выполнение потока дальше. При этом выполняется блок, модифицирующий критические данные. Допустим, в это время истекает квант времени, отпущенный данному потоку, или он вытесняется более приоритетным потоком, использующим те же данные. Новый поток выполняется, пока не встречает функцию EnterCriticalSection, которая помнит, что объект cs уже занят. Новый поток останавливается (засыпает), а остаток процессорного времени передается другому потоку.
Функция LeaveCriticalSection уменьшает счетчик ссылок на объект cs. Как только поток покидает критическую секцию, счетчик ссылок обнуляется и система будит ожидающий поток, снимая защиту секции кодов. Критические секции применяются для синхронизации потоков лишь в пределах одного процесса. Они управляют доступом к данным так, что в каждый конкретный момент времени только один поток может их изменять. Когда надобность в синхронизации потоков отпадает, следует вызвать DeleteCriticalSection (&cs);. Эта функция освобождает все ресурсы, включенные в критическую секцию.