Критичні секції

Ще одним засобом синхронізації потоків служать змінні типу CRITICAL_SECTION. За призначенням вони збігаються з розглянутими вище мьютекс, однак реалізація двійкового семафора в цьому випадку абсолютно інша. Якщо мьютекс - це один з типів об'єктів ядра, то критичні секції - просто змінні. У чому тут принципова різниця? У тому, що об'єкти існують в пам'яті системи, тому прикладна програма не може напряму звернутися до об'єкта, прочитати або записати його значення. Програма може тільки отримати хендл об'єкта, а потім вона доручає системі виконати ту чи іншу дію з об'єктом, на який вказує даний хендл. Таке рішення дозволяє використовувати один об'єкт для зв'язку декількох процесів, зберігаючи при цьому ізоляцію пам'яті процесу від пам'яті системи і інших процесів.

Недолік використання об'єктів ядра в тому, що звернення до них всякий раз вимагає перемикання контексту з користувальницького на системний і назад, а це вимагає часу. Така ціна ізоляції процесів.

Якщо потрібно синхронізувати роботу ниток одного і того ж процесу, то більш «дешевим» рішенням може бути використання змінних CRITICAL_SECTION. Програміст повинен описати змінну цього типу в програмі процесу, при цьому для всіх ниток процесу буде доступний адресу цієї змінної. Перед початком роботи з критичною секцією одна з ниток процесу повинна викликати функцію InitializeCriticalSection, передавши їй адресу змінної. Потім він може використовувати функцію EnterCriticalSection, щоб зайняти двійковий семафор, і функцію LeaveCriticalSection, щоб звільнити його. Як і для мьютекса, один і той же потік може кілька разів зайняти критичну секцію, але потім повинен стільки ж разів звільнити її. Є ще зручна функція TryEnterCriticalSection, яка дозволяє уникнути блокування і займає критичну секцію, тільки якщо та була вільна у момент звернення. Після закінчення необхідності в синхронізації ниток слід викликати функцію DeleteCriticalSection.

Виклик всіх перерахованих функцій виконується системою набагато швидше, ніж виклик функцій, що працюють з хендл об'єктів, оскільки вся робота виконується в пам'яті зухвалого процесу, без перемикання контексту пам'яті. Але зате неможливо використовувати критичні секції для синхронізації ниток різних потоків, для цього потрібні мьютекс.