
- •Глава OS3: Многопоточность
- •Права
- •План части 3.1.
- •Проблема критических секций
- •Решение проблемы критической секции
- •Решения проблемы
- •Первый вариант: Алгоритм 1
- •Второй вариант: Алгоритм 2
- •Третий вариант: Алгоритм 3
- •Алгоритм Деккера (1965)
- •Алгоритм Деккера (продолж.)
- •Алгоритм Бейкери
- •Алгоритм Бейкери
- •Алгоритм Бейкери
- •Взаимоисключение – аппаратная поддержка
- •Устройства синхронизации
- •Взаимоисключение с
- •Устройства синхронизации
- •Взаимоисключение и обмен
- •Семафоры
- •Критические секции n потоков
- •Реализация семафоров
- •Реализация
- •Семафоры как основной метод синхронизации
- •Два типа семафоров
- •Замыкание и нехватка ресурсов
- •Синхронизация в Windows
- •Синхронизация в Линукс
- •Для дальнейшего чтения

Критические секции n потоков
Общие данные:
semaphore mutex; //изначально = 1
Поток Ti:
do {
wait(mutex); критическая секция
signal(mutex); остальные секции
} while (1);
2

Реализация семафоров
Семафоры могут останавливать/продолжать потоки
Избегать ожидания завершения работы
Определите семофор как запись typedef struct {
int value; struct thread *L;
} semaphore;
Реализуйте две простые операции:
suspend() останавливает поток, который вызывает метод.
resume(T) восстанавливает исполнение потока T.
2

Реализация
Операции семафора теперь определены как
wait(S):
S.value--;
if (S.value < 0) {
добавить этот поток к S.L; suspend();
}
signal(S):
S.value++;
if (S.value <= 0) {
убрать поток T из S.L; resume(T);
}
2

Семафоры как основной метод синхронизации
Выполняйте B в Tj только после завершения работы A в Ti
Используйте семафор flag инициализированный 0
Код:
Ti Tj
… …
A wait(flag) signal(flag) B
2

Два типа семафоров
Вычислительные семафоры
Целое значение может быть числом в неограниченном диапазоне
Двоичные семафоры
Целое значение может быть только 0 или 1;
Может быть проще в реализации.
Вычислительный семафор S может быть реализован как двоичный семафор.
2

Замыкание и нехватка ресурсов
Замыкание – два или более потоков ожидают события, которое может быть послано только ожидающим потоком.
Пусть S и Q будут двумя семафорами, инициализированными 1
T0 T1 wait(S); wait(Q); wait(Q); wait(S);
……
signal(S); signal(Q); signal(Q) signal(S);
Нехватка ресурсов – бесконечное блокирование. Поток может никогда не быть убран с очереди семафора, в котором он остановлен.
Решение – весь код должен проставлять/убирать семафоры в одинаковом порядке
2

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

Синхронизация в Линукс
Ядро запрещает прерывания для синхронизирующего доступа к глобальный информации на однопроцессорных системах.
Использует spinlocks для многопроцессорной синхронизации.
Использует семафоры и замки чтения-записи когда длинные участки кода требуют доступа к данным.
Реализуют POSIX-синхронизацию примитивов для поддержки многозадачности, многопоточности (включая потоки реального времени) и мультипроцессорности
2

Для дальнейшего чтения
Ben-Ari, M., Principles of Concurrent Programming, Prentice Hall, 1982
Lamport, L., The Mutual Exclusion Problem, Journal of the ACM, April 1986
Abraham Silberschatz, Peter B. Galvin, Operating System Concepts, John Wiley & Sons, 6th Ed., 2003;
Chapter 7 - Process Synchronization
Chapter 8 – Deadlocks
2