Paralelní programování Synchronizace – čtenáři – písaři
Čtenáři – písaři více konzumentů více producentů konzument neodebírá data z paměti čtení se může provádět souběžně zápis vylučuje čtení a naopak ale od každého může být více instancí kategorické vyloučení
Písař roomEmpty.wait() writedata() roomEmpty.signal()
Čtenář mutex.wait() readers = readers + 1 if readers == 1 roomempty.wait() mutex.signal() readdata() readers = readers – 1 if readers == 0 roomEmpty.signal()
Optimalizace poslední odejde a zhasne písaři stárnou lock() unlock() vzor lightswitch písaři stárnou pokud stále přichází čtenáři, je potřeba zajistit, aby se dostalo i na písaře v algoritmu je implicitně zavedená priorita velmi zrádné – není vidět na první pohled
Písař turnstile.wait() roomEmpty.wait() writedata() turnstile.signal() roomEmpty.signal()
Čtenář turnstile.wait() turnstile.signal() mutex.wait() readers = readers + 1 if readers == 1 roomempty.wait() mutex.signal() readdata() readers = readers – 1 if readers == 0 roomEmpty.signal()
Optimalizace na písaře se rozhodně dostane nový požadavek ale nevíme přesně kdy zavedli jsme do algoritmu jinou implicitní prioritu plánovač zde nemůže pomoci nový požadavek pokud čeká písař, už nesmí vstoupit žádný další čtenář implicitní prioritu lze dále zvýšit
Čtenář noReaders.wait() mutex1.wait() readers = readers + 1 if readers == 1: noWriters.wait() mutex1.signal() noReaders.signal() readdata() readers = readers - 1 if readers == 0: noWriters.signal()
Písař mutex2.wait() writers = writers + 1 if writers == 1: noReaders.wait() mutex2.signal() noWriters.wait() writedata() noWriters.signal() writers = writers - 1 if writers == 0: noReaders.signal()
Dining philosophers omezené zdroje (různého) druhu pro pokračování jsou potřeba alespoň 2 zdroje je nutné zabránit stárnutí a uváznutí musí pokračovat více jak jedno vlákno – je nutné zachovat efektivitu zdroj může být obsazen pouze jedním procesem
Filozof forks = array[0..cnt] of sem(1) function get_forks(i) fork(i).wait() fork(i+1 % cnt).wait() function put_forks(i) fork(i).signal() fork(i+1 % cnt).signal()
Filozof forks = array[0..cnt] of sem(1) function get_forks(i) room.wait() fork(i).wait() fork(i+1 % cnt).wait() function put_forks(i) room.signal() fork(i).signal() fork(i+1 % cnt).signal()
Varianty nesymetrické řešení testování zda je možné pokračovat jedno z vláken je levé testování zda je možné pokračovat více typů zdrojů
Producent – konzument 2 producent je jeden a nic nedělá pokud je buffer prázdný, konzument požádá o naplnění producent naplní buffer na maximum konzumenti začnou konzumovat kuchař a žrouti synchronizace výstupu
Producent while (true) bufferEmpty.wait() fillbuffer(size) cnt == size bufferFull.signal()
Konzument while (true) mutex.wait() if (cnt == 0) bufferEmpty.signal() bufferFull.wait() cnt =- 1 d = getData() mutex.signal() processData(d)
Shrnutí celá řada modifikací např. delete – update – insert – select kategorické vyloučení je náchylné ke stárnutí vlákno čekající na více semaforů je náchylné k uváznutí je nutné stanovit si pravidla je potřeba snažit se o maximální efektivitu stárnutí není jen problém plánovače