Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
СППО .doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
190.46 Кб
Скачать

12. Синхронизация потоков. Критические секции

При доступе потоков к общим ресурсам возникают коллизии. Предотвратить коллизии можно с помощью различных средств синхронизации, одним из которых является критическая секция. Все потоки в системе должны иметь доступ к системным ресурсам — кучам, последовательным портам, файлам, окнам и т.д. Если один из потоков запросит монопольный доступ к какому-либо ресурсу, другим потокам, которым тоже нужен этот ресурс, не удастся выполнить свои задачи. А с другой стороны, просто недопустимо, чтобы потоки бесконтрольно пользовались ресурсами. Иначе может получиться так, что один поток пишет в блок памяти, из которого другой что-то считывает.

Потоки должны взаимодействовать друг с другом в двух основных случаях:

  • совместно используя разделяемый ресурс (чтобы не разрушить его);

  • когда нужно уведомлять другие потоки о завершении каких-либо операций.

Критические секции

В начале критической секции необходимо вызвать подпрограмму api

procedure EnterCriticalSection (sect:TRTLCriticalSection);

которая проверяет состояние записи sect: TRTLCriticalSection и, если в записи секция помечена как занятая другим потоком, приостанавливает текущий поток, пока критическая секция не освободится.

В конце критической секции вызывается подпрограмма

procedure LeaveCriticalSection (sect:TRTLCriticalSection);

которая делает пометку в записи, что критическая секция свободна, и другой поток в соответствии с приоритетом получает квант времени и входит в критическую секцию.

Предварительно перед использованием необходимо проинициализировать запись sect: TRTLCriticalSection с помощью процедуры

procedure InitializeCriticalSection(Sect);

а при завершении использования – удалить:

procedure DeleteCriticalSection(Sect1);

Примерная схема программы может выглядеть следующим образом.

CRITICAL_SECTION cs;

DWORD WINAPI SecondThread()

{

InitializeCriticalSection(&cs);

EnterCriticalSection(&cs);

… критический участок кода

LeaveCriticalSection(&cs);

}

main ()

{

InitializeCriticalSection(&cs);

CreateThread(NULL, 0, SecondThread,…);

EnterCriticalSection(&cs);

… критический участок кода

LeaveCriticalSecLion(&cs);

DeleteCriticalSection(&cs);

}

13. Объекты синхронизации и функции ожидания

Объектами синхронизации называются объекты Windows, идентификаторы которых могут использоваться в функциях синхронизации. Они делятся на две группы – объекты, использующиеся только для синхронизации и объекты, которые используются в других целях, но могут вызывать срабатывание функций ожидания. К первой группе относятся:семафоры, мьютексы, события и т.д. Ко второй группе относятся потоки, процессы и т.д.

Главные понятия для понимания механизмов синхронизации — функции ожидания и объекты синхронизации. В Windows API предусмотрен ряд функций, позволяющих приостановить выполнение вызвавшего эту функцию потока вплоть до того момента, как будет изменено состояние какого-то объекта, называемого объектом синхронизации (под этим термином здесь понимается не объект Delphi, а объект операционной системы). Простейшая из этих функций — waitForSingieCbject — предназначена для ожидания одного объекта. К возможным вариантам относятся четыре объекта, которые разработаны специально для синхронизации: событие (event), взаимное исключение (mutex), семафор (semaphore).

Но кроме специальных объектов можно организовать ожидание и других объектов, дескриптор которых используется в основном для иных целей, но может применяться и для ожидания. К ним относятся: процесс (process), поток (thread), оповещение об изменении в файловой системе (change notification) и консольный ввод (console input).

Косвенно к этой группе может быть добавлена критическая секция (critical section).