Синхронизация потоков. Способы синхронизации. Переменная-замок. TSL-команды. Interlocked-функции
Взаимосвязанные потоки, которые обмениваются данными или пользуются одними и теми же устройствами ввода-вывода, должны синхронизировать свою работу для исключения неправильной работы объектов или сбою ОС. Проблема синхронизации, которая возникает в подобных случаях, может решаться приостановкой и активизацией потоков, организацией очередей, блокированием и освобождением ресурсов.
Сложность проблемы синхронизации состоит в нерегулярности возникающих ситуаций (условия состязания). Для устранения условий состязания необходимо обеспечить каждому потоку эксклюзивный доступ к разделяемым данным. Такой прием называется взаимоисключением, которое надо обеспечить для части кода потока (критической секции), выполнение которого может привести к «состязанию».
Переменная-замок
Можно сделать условием вхождения в критическую секцию значение 0 некоторой разделяемой переменной lock. Сразу же после проверки это значение меняется на 1 (закрытие замка). При выходе из критической секции замок открывается (значение переменной lock сбрасывается в 0).
shared int lock = 0;
while (some condition) {
while(lock);
lock = 1;
critical section
lock = 0;
remainder section }
Недостаток: работает не всегда. действие из двух операций while(lock); lock = 1; не является атомарным, существует вероятность вытеснения потока между ними. Управление м/перейти ко второму потоку, который войдет в свою критическую секцию.
|
|
TSL команды
Команды Test_and_Set Lock (TSL-команды) обеспечивают атомарность последовательности операций при входе в критическую секцию. Если представить себе такую команду как функцию
int TSL (int *target)
{ int tmp = *target;
*target = 1;
return tmp; }
Заменив операции [while(lock); lock = 1;] на TSL(lock), мы решаем проблему взаимоисключения.
Interlocked-функции
Входят в состав NIP. Например Interlocked Exchchange Add (PLONG, plAdd, LONG)
Функции выполняются в режиме пользователя за короткое время.
Синхронизация потоков. Способы синхронизации. Спин-блокировка. Функции семейства CryticalSection
Взаимосвязанные потоки, которые обмениваются данными или пользуются одними и теми же устройствами ввода-вывода, должны синхронизировать свою работу для исключения неправильной работы объектов или сбою ОС. Проблема синхронизации, которая возникает в подобных случаях, может решаться приостановкой и активизацией потоков, организацией очередей, блокированием и освобождением ресурсов.
Сложность проблемы синхронизации состоит в нерегулярности возникающих ситуаций (условия состязания). Для устранения условий состязания необходимо обеспечить каждому потоку эксклюзивный доступ к разделяемым данным. Такой прием называется взаимоисключением, которое надо обеспечить для части кода потока (критической секции), выполнение которого может привести к «состязанию».
|
|
Спин-блокировка
Перед входом в критическую область, поток проверяет возможность входа и, ели такой возможности нет, продолжает определение переменной замка. Поведение потока, связанное с обращением в пустом цикле, называемой spin-блокировкой. На однопроцессорной машине это пустая трата времени, однако на многопроцессорных машинах временная spin-блокировка м.б. полезна, поскольку поток, поток, работающий на другом процессоре может изменить значение переменной замка. На однопроцессорной машине более разумным будет немедленный перевод потока в состояние ожидания.
Функции семейства CryticalSection
В составе WNP входят специальные спец. Функции для организации работы с критической областью EnterCryticalSection и LeaveCryticalSection. В качестве параметра они имеют заранее инициализированную структуру CRITICAL_SELECTION
main ()
{InitializeCriticalSection(&cs);
CreateThread(NULL, 0, SecondThread,…);
EnterCriticalSection(&cs);
… критический участок кода
LeaveCriticalSecLion(&cs);
DeleteCriticalSection(&cs);}
EnterCriticalSection и LeaveCriticalSection реализованы на основе Interlocked-функций, выполняются атомарным образом и работают очень быстро. Существенным является то, что в случае невозможности входа в критический участок поток переходит в состояние ожидания.
|
|
22. Синхронизация потоков. Способы синхронизации. Синхронизация с использованием объектов ядра
Взаимосвязанные потоки, которые обмениваются данными или пользуются одними и теми же устройствами ввода-вывода, должны синхронизировать свою работу для исключения неправильной работы объектов или сбою ОС. Проблема синхронизации, которая возникает в подобных случаях, может решаться приостановкой и активизацией потоков, организацией очередей, блокированием и освобождением ресурсов.
Сложность проблемы синхронизации состоит в нерегулярности возникающих ситуаций (условия состязания). Для устранения условий состязания необходимо обеспечить каждому потоку эксклюзивный доступ к разделяемым данным. Такой прием называется взаимоисключением, которое надо обеспечить для части кода потока (критической секции), выполнение которого может привести к «состязанию».
Задачу синхронизации потоков различных процессов принято решать с помощью объектов ядра. Они работают несколько медленнее критических секций.
О каждом из объектов можно сказать, находится ли он в свободном или занятом состоянии. Если поток выполняется - он в занятом состоянии, если поток завершил ожидание семафора - семафор находится в занятом состоянии.
|
|
Для приостановки потока и перевода его в состояние ожидания освобождения объекта используется функция
WaitForSingleObject с параметрами (описатель ожидаемого объекта ядра, max время ожидания объекта).
Семафоры
Доступ через две атомарные операции: wait и signal (WaitForSingleObject и ReleaseSemaphore соотв.).
wait(S): если S <= 0 процесс блокируется
(переводится в состояние ожидания);
в противном случае S = S - 1;
signal(S): S = S + 1
Семафоры обычно используются для учета ресурсов (текущее число ресурсов задается переменной S) и создаются при помощи функции CreateSemaphore, в число параметров которой входят начальное и максимальное значение переменной. Текущее значение не может быть больше max и отрицательным. S =0 означает, что семафор занят.
Мьютексы
Мьютексы также представляют собой объекты ядра, используемые для синхронизации, но они проще семафоров, так как регулируют доступ к единственному ресурсу и, следовательно, не содержат счетчиков. По существу они ведут себя как критические секции, но могут синхронизировать доступ потоков разных процессов.
Инициализация - CreateMutex, вход в критическую секцию - WaitForSingleObject, выход - ReleaseMutex.
События
Предназначены для информирования одного потока другим об окончании какой-либо операции. События создаются ф-й CreateEvent. Простейший вариант синхронизации: переводить событие в занятое состояние функцией WaitForSingleObject и в свободное - функцией SetEvent.
Дата добавления: 2018-05-31; просмотров: 587; Мы поможем в написании вашей работы! |
Мы поможем в написании ваших работ!