12. Основные примитивы синхронизации потоков
В одном процессе может выполняться сколько угодно потоков, а если есть несколько потоков, то их нужно синхронизировать.
int n=0, f=0;
while (1) { while (1) {
while (!f); while (f);
n++, n++; if (n…)
f=0;} f=1;
Минусы данной синхронизации:
-
впустую тратится энергия и процессорное время
-
если переменных больше одной, то возникнут трудности
При выполнении параллельных процессов может возникать проблема, когда каждый процесс, обращающийся к разделяемым данным, исключает для всех других процессов возможность одновременного с ним обращения к этим данным - это называется взаимоисключением
Поэтому современные ОС содержат такое понятие mutex (взаимное исключение) это позволяет чтобы потоки выполнялись непрерывно – это обычный флажок.
С mutex возможны 2 операции: lock(m)- заблокировать и unlock(m)- разблокировать. Это обуславливает поочередный доступ к общему ресурсу.
Mutex – это частный случай «Семафора». В основе семафора – счетчик n.
При каждом захвате из счетчика вычитается 1, когда станет 0 – следующий захват заблокирует всех. «Семафор» нужен для защиты однородных ресурсов. Таким образом, синхронизация решается методом поочередной блокировки с помощью семафора и mutex.
Не все виды синхронизации решаются данным способом, поэтому существует второй вид – синхронизация по времени (должно произойти некоторое событие, которого дожидается программа). Для этого используется «условная переменная» q-war (Unix), event (Windows). С этим понятием можно использовать две операции: wait (E)- ждать сигнал и Signal (E)- послать сигнал, причем события не гарантируют, что потоки не проспят сигнал.