3. cvičení - Semafory
Užitečné odkazy
Semaphore Objects
Semafor je nejstarší synchronizační primitivum vytvořené informatikem Edsger W. Dijkstrou, který používal názvy
P()
a V()
místo acqiure()
a release()
.
Semafor interně obsahuje čítač, kdy každé volání acquire()
dekrementuje tento vnitřní čítač a volání release()
tento čítač inkrementuje. Hodnota tohot čítače nikdy neklesne do záporných hodnot, v případě, že je jeho hodnota
rovna 0
a zavoláme acquire()
tak volání blokuje dané vlákno do doby než jiné vlákno zavolá release()
.
import threading
# Vytvoření semaforu
mutex = threading.Semaphore(1)
def function_with_critical_section():
global mutex
# Nekritická sekce
mutex.acquire()
# Kritická sekce
mutex.release()
# Vytvoření vláken
t1 = threading.Thread(target=function_with_critical_section)
t2 = threading.Thread(target=function_with_critical_section)
t1.start()
t2.start()
t1.join()
t2.join()
# V kritické sekci múže dojít k chybě jako neexistující soubor,
# program nemá právo číst/zapisovat do souboru, apod.
# Musíme tedy zajistit, že i při chybě dojde k uvolnění mutexu.
mutex.acquire()
try:
# Kód, kde může dojít k vyjímce
finally:
# Tento blok se vykoná pokaždé bez ohledu na to jestli chyba nastala či ne.
mutex.release()
# Výše uvedenou kontrukci můžeme zapsat pomocí with
with mutex:
# Kód, kde může dojít k vyjímce
Úkoly
Upravte úkol 1 ze 2. cvičení tak, aby přístup ke sdílené proměnné byl synchronizován.
Napište program, kde budou 3 procesy. První bude producent a bude generovat dvojice náhodných čísel. Druhý proces bude zjíšťovat jestli jsou tato dvě čísla soudělná. Pokud ne, tak bude třetímu procesu poslána 1 jinak 0. Třetí proces bude počítat počet jedniček a počet všech čísel která mu pošle druhý proces.
(Bodovaný) Upravte druhý úkol tak, aby program skončil pokud třetí proces obdrží N jedniček.