*Otázka obsahuje i synchronizační primitiva z předchozí otázky.

ThreadPool

  • Návrhový vzor i běžný nástroj.
  • Úkoly se ukládají do fronty a postupně jsou jim přidělována vlákna.
  • Odpadá režie znovuvytvoření vláken (zrychlení, menší režie).
  • Běžně dostupné v jazycích.

Klasické paralelní problémy

  • Večeřící filozofové
  • Producent-konzument
  • Čtenáři a písaři
  • Hodující divoši
  • Holičství
  • Santa Clause
  • Sushi bar
  • Jídelna

Večeřící filozofové

  • Procesy požadující více sdílených zdrojů.
  • Jeden typ procesu - filozof- se dvěma operacemi:
    • jí (vyžaduje zdroje),
    • přemýšlí (nevyžaduje zdroje).

Problém:

filozofů sedí u kulatého stolu a mezi každou dvojící leží jedna vidlička. Jíst může, pokud má dvě vidličky. Vidličku nemůže mít více filozofů.

  • Je potřeba synchronizace lehce může dojít k deadlocku.

Řešení:

  1. Jeden filozof je levák a zdvihá vidličky naopak (není efektivní a férové - u některých zdrojů určit prioritu)
  2. Číšník - Máme vlákno, které zajistí koordinace (velké plýtvání zdroji, může dojít k vyhladovění - filozofové se budou předbíhat)
  3. Zvedne vidličku, nemůže získat, tak položí (může vzniknout livelock)
  4. Budeme mít jen 4 židle (nevznikne deadlock, ale musíme vyřešit filozofy sdílející vidličku)

Producent-konzument

  • Reálný, často používaný problém.

Problém:

Producenti produkují, konzumenti konzumují a sdílejí omezený prostor - nelze tedy přepsat nezkonzumované a nelze opakovaně konzumovat

  • Typicky máme více producentů a konzumentů
  • Komunikují přes buffer.
    • Když někdo přidává/odebírá data do/z bufferu, buffer není v konzistentním stavu.
    • přístup k bufferu musí být ve vzájemném vyloučení.
  • Cílem bufferu není řešit rozdíl v rychlosti procesů.

Řešení:

  • Dva semafory (not_empty, not_full) a zámek (zápis na místo v poli)
  • Zjednodušeně:
# Producent
  item = produce_item() #produkce
  
  not_full.wait()                # Čekej, dokud není místo v bufferu
  mutex.acquire()                # Získání zámku
  # uložení položky na buffer
  mutex.release()                # Uvolnění zámku
  not_empty.signal()             # Signalizuj, že buffer není prázdný
 
# Konzument
  not_empty.wait()             # Čekej, dokud není něco v bufferu
  mutex.acquire()              # Získání zámku
  # konzumace
  mutex.release()               # Uvolnění zámku
  not_full.signal()             # Signalizuj, že buffer není plný

Čtenáři a písaři

  • Reálný, často používaný problém.
  • Dva typy procesů soutěží o přístup k datům:
    • písaři mezi sebou
    • čtenáři jako třída s písaři
  • Písaři musí psát ve vzájemném vyloučení.
  • Čtenáři jako třída vylučuje písaře. Mohou však číst zároveň.
  • Např. přístup k souboru, DB, datové struktuře, …

Řešení:

  • Obecně přímočaré, ale je třeba dávat pozor na spravedlivost (preference čtenářů nebo písařů)

  • Některé jazyky mají RWlock

Nespravedlivé řešení - upřednostňuje čtenáře: Ř1: Získání přístupu k počtu čtenářů Ř3: Pokud jde o prvního čtenáře, blokuj písaře Ř4: Uvolni přístup k počtu čtenářů Ř8: Poslední čtenář uvolňuje zámek pro písaře

Spravedlivé řešení

Kuřáci

  • Agent má zdroje - papír, tabák a sirky
  • Existují tři typy kuřáků:
    1. Ti co mají papír
    2. Ti co mají tabák
    3. Ti co mají sirky
  • Agent opakovaně dává k dispozici dva náhodné zdroje. Cílem je, aby kuřák, který může pokračovat, pokračoval.

Motivace v OS

Existují tři verze:

  1. Nemožná: Nelze měnit kód agenta a není možné použít větvení a pole semaforů (neřešitelné)
  2. Zajímavá: Nelze měnit kód agenta
  3. Triviální: Lze měnit kód agenta

Hodující divoši

  • divochů jí porcí misionáře z hrnce. Pokud dojdou, požádají kuchaře o navaření dalších porcí.