
- •1.1 Основы программирования в операционной системе Windows
- •1.1.1 Вызов функций api
- •1.1.2 Структура программы
- •1.2 Вопросы системного программирования в Windows
- •1.2.1 Страничная и сегментная адресация.
- •1.2.2 Адресное пространство процесса.
- •2.1 Управление процессами
- •2.2 Процессы и потоки в Windows
- •2.3 Создание процессов
- •2.4 Определение исполняемого образа и командной строки
- •2.5 Идентификация процессов
- •3.1 Создание потока. Функция CreateThread
- •3.2. Завершение потока
- •3.3 Другие функции работы с потоками
- •3.4 Структура context
- •3.5 Приоритеты потоков
- •4.1 Объект critical_section
- •4.2 Мьютексы
- •4.3 Семафоры
- •5.1 События
- •7.1 Кучи
- •7.2 Управление памятью кучи
- •Другие функции для работы с кучей
- •Резюме по управлению кучей
- •Отображение адресного пространства процесса в объекты отображения
- •Что такое импорт
- •Явная загрузка dll
- •Явное подключение экспортируемого идентификатора
- •10.1 Управление файлами и каталогами Создание и открытие файлов
- •10.2 Управление каталогами
- •10.3 Другие методы получения атрибутов файлов и каталогов
- •11.1 Блокировка файлов
- •11.2 Реестр
- •12.1 Стандартные устройства и консольный ввод-вывод
- •12.2 Асинхронный ввод-вывод и порты завершения
- •Параметры
- •Цели системы безопасности
- •Параметры
- •Аварийное завершение
- •Использование именованных каналов
- •Параметры
- •Наблюдение за сообщениями в именованном канале
- •Параметры
4.1 Объект critical_section
Критическая секция — это часть кода, которая одновременно может выполняться только одним потоком; выполнение такой секции одновременно более чем одним потоком может привести к непредсказуемым и неверным результатам.
В качестве простого механизма для реализации идеи критической секции Win32 предоставляет объект CRITICAL_SECTION.
Объекты типа CRITICAL_SECTTON (критическая секция — КС) могут быть инициализированы и удалены, но они не имеют дескрипторов и не разделяются другими процессами. Переменная должна быть определена как имеющая тип CRITICAL_SECTION. Потоки входят в КС и покидают ее, но одновременно в КС может находиться только один поток. Однако поток может входить в КС и покидать ее в нескольких местах программы.
Для инициализации и удаления переменной типа CRITICAL_SECTION используйте следующие функции:
VOID InitializeCriticalSection (
LPCRITICAL_SECTION lpcsCritical Section)
VOID DeleteCriticalSection (
LPCRITICAL_SECTION lpcsCriticalSection)
Функция EnterCriticalSection блокирует поток, если в данной секции находится другой поток. С ожидающего потока снимается блокировка, когда другой поток выполняет функцию LeaveCritcicalSection. Мы говорим, что поток "владеет" КС с того момента, когда он получает управление от функции EnterCriticalSection, по тот момент, как функция LeaveCriticalSection отдает владение КС. Всегда отдавайте владение КС; если этого не сделать, другие потоки вынуждены будут ожидать вечно, даже если владеющий поток будет завершен.
Мы часто будем говорить, что КС "блокирована" или "разблокирована", а вхождение в КС — то же самое, что и ее блокировка.
VOID EnterCriticalSection (
LPCRITICAL_SECTION lpcsCriticalSecticn)
VOID LeaveCriticalSection (
LPCRITICAL _ SECTION lpcsCriticalSecticn)
Если поток уже владеет КС, он может войти в нее снова без блокировки. Поддерживается счетчик, поэтому поток должен покинуть КС столько же раз, сколько он вошел в нее, чтобы освободить КС для других потоков.
Выход из КС, которой данный поток не владеет, может привести к непредсказуемым результатам, включая блокировку потока.
Для функции EnterCriticalSection время ожидания не ограничивается, поток будет заблокирован до того момента, когда поток, владеющий КС, выйдет из нее. Можно провести проверку или опрос, чтобы узнать, владеет ли КС какой-нибудь другой поток, используя функцию TryEnterCriticalSection.
BOOL TryEnterCriticalSection (
LPCRITICAL_SECTION lpcsCriticalSection)
Возвращенное значение TRUE показывает, что вызвавший функцию поток теперь владеет КС, а значение FALSE показывает, что КС уже занята другим потоком.
Объекты CRITICAL_SECTION имеют преимущество в том, что не являются объектами ядра и располагаются в пользовательском пространстве.
Управление счетчиком попыток
Если при выполнении функции EnterCriticalSection поток определяет, что КС уже занята, он обычно входит в ядро и блокируется до освобождения объекта CRITICAL_SECTION, что требует временных затрат. Но вы можете заставить поток сделать еще одну попытку перед блокировкой. Для управления счетчиком попыток существуют две функции: SetCriticalSectionSpinCount, которая позволяет динамически изменять счетчик, и InitializeCriticalSectionAndSpinCount, которая служит заменой функции InitializeCriticalSection.
Объект CRITICAL_SECTION является мощным механизмом синхронизации, хотя и не имеет всей необходимой функциональности. Он не предоставляет возможности передачи сигнала другому потоку и не дает возможности установить максимальное время ожидания (тайм-аут).