- •Глава OS3: Многопоточность
- •Права
- •План части 3.1.
- •Проблема критических секций
- •Решение проблемы критической секции
- •Решения проблемы
- •Первый вариант: Алгоритм 1
- •Второй вариант: Алгоритм 2
- •Третий вариант: Алгоритм 3
- •Алгоритм Деккера (1965)
- •Алгоритм Деккера (продолж.)
- •Алгоритм Бейкери
- •Алгоритм Бейкери
- •Алгоритм Бейкери
- •Взаимоисключение – аппаратная поддержка
- •Устройства синхронизации
- •Взаимоисключение с
- •Устройства синхронизации
- •Взаимоисключение и обмен
- •Семафоры
- •Критические секции n потоков
- •Реализация семафоров
- •Реализация
- •Семафоры как основной метод синхронизации
- •Два типа семафоров
- •Замыкание и нехватка ресурсов
- •Синхронизация в Windows
- •Синхронизация в Линукс
- •Для дальнейшего чтения
Алгоритм Деккера (продолж.)
Инициализация общих переменных:
int flag[2]; flag[0] = flag[1] = 0; int turn = 0;
Поток Ti
do { flag[i] = 1;
while (flag[j] ) if (turn == j) {
flag[i] = 0; while (turn == j); flag[i] = 1;
}
критическая секция
turn = j; flag[I] = 0;;
остальные секции
} while (1);
1
Алгоритм Бейкери
(Лэмпорт 1979)
Решение проблемы Критической Секции для n потоков
Перед входом в критическую секцию, потоку присваивается номер. Поток с наименьшим номером входит в критическую секцию.
Если поток Ti и Tj получают одинаковый номер, если i < j, тогда Ti обслуживается первым; иначе Tj обслуживается первым.
Схема нумерации генерирует монотонную неубываемую последовательность; напр., 1,1,1,2,3,3,3,4,4,5...
1
Алгоритм Бейкери
Нотация “<“ устанавливает лексикографический порядок между двумя тьюплами (тикет #, поток #)
(a,b) < (c,d) if a < c or if a == c and b < d
max (a0,…, an-1) = { k | k ai for i = 0,…, n – 1 }
Общая информация
int |
choosing[n]; |
|
int |
number[n]; |
- тикет |
Структуры данных инициализированы 0
1
Алгоритм Бейкери
do {
choosing[i] = 1;
number[i] = max(number[0],number[1] ...,number[n-1]) + 1; choosing[i] = 0;
for (j = 0; j < n; j++) { while (choosing[j] == 1) ;
while ((number[j] != 0) &&
((number[j],j) ‘’<‘’ (number[i],i)));
}
критическая секция number[i] = 0;
остальные секции } while (1);
1
Взаимоисключение – аппаратная поддержка
Запрет прерываний
Конкурирующие потоки не могут обращаться к одному процессору
Поток работает до получения системного вызова или прерывания
Специальные атомарные машинные инструкции
Инструкции Test и Set – читать и писать в память
Инструкция Exchange (обмен) – обмен между регистром и памятью
Проблемы с подходом через машинные инструкции
Ожидание завершения работы
Возможен недостаток ресурсов Возможно замыкание на одном процессе
1
Устройства синхронизации
Атомарная проверка и модификация содержимого слова
boolean TestAndSet(boolean &target) { boolean rv = target;
target = true;
return rv;
}
1
Взаимоисключение с |
Test- |
и-Set инструкциями |
|
Общие данные:
boolean lock = false;
Поток Ti
do {
while (TestAndSet(lock)) ; критическая секция
lock = false; остальные секции
}
1
Устройства синхронизации
Атомарный обмен двух переменных.
void Swap(boolean &a, boolean &b) { boolean temp = a;
a = b;
b = temp;
}
1
Взаимоисключение и обмен
Общие данные (инициализированы 0):
int lock = 0;
Поток Ti
int key; do {
key = 1;
while (key == 1) Swap(lock,key);
критическая секция lock = 0;
остальные секции
}
1
Семафоры
Семафор S – целочисленная переменная
Доступ может быть получен только через две атомарные операции
wait (S):
while (S <= 0); S--;
signal (S):
S++;
2
