Синхронизация потоков. Способы синхронизации. Переменная-замок. 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; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!