Существует два типа реализующих синхронизацию процесса:
1 взаимное исключение
2 условная синхронизация.
Во взаимном исключении организуется исключающий доступ к общим ресурсам (переменным) единственного потока или процесса.
В условной синхронизации не допускается исполнение треб. операции или программы пока не будет достигнуто условие треб. программы.
Рассмотрим методы синхронизации взаимного исключения.
Метод реализуется в пользовательском пространстве (программистом), т.е. синхронизация процессов производится без участия операционной системы. Каждому набору критических секций ставится в соответствие глобальная двоичная переменная, которой присваивается значение логической единицы, когда критическая секция свободна и ноль, когда занята.
Запрос к некоторому ресурсу D можно представить следующим алгоритмом:
F(D) – блокирующая переменная, отвечающая за занятость процесса.
Листинг программы «Вход и выход из критической области с помощью команды TSL» на ассемблере.
enter_region;
TSL REGISTER.LOCK ; Значение LOCK копируется в регистр, значение переменной устанавливается в единицу. GMP REGISTER.#0 ; Старое значение lock сравнивается с нулем.
JNE enter_region ; Если оно ненулевое, значит, блокировка уже была установлена, поэтому цикл завершается. RET; Возврат к вызывающей программе, процесс вошел в критическую область.
leave_region;
MOVE LOCK .#0; Сохранение 0 в переменной lock
RET
Недостаток метода: запущенный процесс неопределенно долго может находиться в петле ожидания. Процессор, если ему предоставлен квант, постоянно производит сканирование блокирующей переменной, на что бесполезно тратится время.
Однако, возможен вход нескольких процессов в критическую секцию.
Например, пусть некоторый поток, который требует доступы к некоторым ресурсам. Не успев его установить в состояние «занят» он был прерван, например, по истечении кванта.
Другой процесс определяет, что ресурс свободен, занял ресурс, вошел в критическую секцию и был прерван.
Когда первый процесс получит управление он считает, что ресурс свободен, занимает его, и так же входит в критическую секцию. Таким образом, два процесса оказываются в критической секции, что не допустимо.
Чтобы исключить такую ситуацию, можно применить следующие приемы:
- при запросе ресурса запрещать прерывания, однако, такой метод не годится для многопроцессных систем, т.к. запрещается прерывание в одном процессоре, другие процессоры остаются активными.
- использовать неделимую (единую) команду, например, TSL – test and set lock (тестирвать и установить), которая определяет свободен или занят ресурс (test) и устанавливает (set) бит блокировки (lock). В системе команд процессора Pentium имеется две команды :BTS r/m проверить и установить блокирующую переменную и BTR r/m проверить и сбросить блокирующую переменную, размещенную либо в регистре, либо в памяти.
Метод системных вызовов заключается в том, что процесс или поток прежде чем войти в критическую секцию выполняет системный вызов.
В рамках этого вызова выполняется проверка блокирующих переменных, и если ресурс занят, то запрашивающий процесс переходит в режим ожидания, при этом делается отметка о том, что данный процесс или поток должен быть активирован когда ресурс освободится - перечисленные функции выполняет ядро ОС.
Тогда алгоритм будет следующим:
Такой метод исключает бесконечный цикл опроса блокирующих переменных.
Однако, может быть применен к достаточно объемным критическим секциям. Это связано с тем, что системный вызов требует вход в ядро ОС. Вход сопровождается сохранением контекста, а выход восстановление контекста требуемых программ, требует значительных затрат времени.
Блокирующие переменные, использующие системные вызовы, называют мьютексами, этот метод поддерживается почти всеми ОС.
Быстродействие спин-блокировки высокое, т.к. происходит в пространстве пользователя, а не ядра, где возникает необходимость сохранение контекста процесса.