1/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Vláknové programování část II Lukáš Hejmánek, Petr Holub {xhejtman,hopet}@ics.muni.cz Laboratoř pokročilých síťových technologií PV192 2013–02–25 2/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Přehled přednášky Vlákna v jazyce Java Viditelnost a synchronizace Ukončování vláken Monitory a synchronizace Signalizace a suspend Domácí úkol 3/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Přehled přednášky Vlákna v jazyce Java Viditelnost a synchronizace Ukončování vláken Monitory a synchronizace Signalizace a suspend Domácí úkol 4/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Vlákna v jazyce Java Mechanismy ◾ potomek třídy Thread ◾ Executory ◾ objekt implementující úlohu pro Executor objekt implementující interface Runnable (metoda run()) objekt implementující interface Callable (metoda call()) Synchronizace a viditelnost operací Implementace monitorů pomocí synchronized Signalizace mezi objekty: wait, notify, notifyAll Knihovny java.util.concurrent 5/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Třída Thread Základní třída pro vlákna Metoda run() ◾ „vnitřnosti“ vlákna ◾ přepisuje se vlastním kódem Metoda start() ◾ startování vlákna ◾ za normálních okolností nepřepisuje! ◾ pokud už se přepisuje, je třeba volat super.start() 6/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Třída Thread 1 public class PrikladVlakna { 3 static class MojeVlakno extends Thread { MojeVlakno(String jmenoVlakna) { 5 super(jmenoVlakna); } 7 public void run() { 9 for (int i = 0; i < 10; i++) { System.out.println(this.getName() + 11 ": pocitam vzbuzeni - " + (i + 1)); try { 13 sleep(Math.round(Math.random())); } catch (InterruptedException e) { 15 System.out.println(this.getName() + ": probudil jsem se nenadale! :-|"); 17 } } 19 } } 7/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Třída Thread public static void main(String[] args) { 2 new MojeVlakno("vlakno1").start(); new MojeVlakno("vlakno2").start(); 4 } } 8/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Viditelnost a synchronizace operací problém viditelnosti změn problém atomicity operací ◾ např. přiřazení do 64-bitového typu (long, double) není nutně atomický! problém synchronizace při změnách hodnot § ¦ ¤ ¥ (nic) > volatile > AtomicXXX > synchronized, explicitní zámky 9/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Viditelnost a synchronizace operací public class Nic { 2 private static long cislo = 10000000L; private static boolean pripraven = false; 4 public static class Vlakno extends Thread { 6 public void run() { while (!pripraven) { 8 Thread.yield(); } 10 System.out.println(cislo); } 12 } 14 public static void main(String[] args) { new Vlakno().start(); 16 cislo = 42L; pripraven = true; 18 } } § ¦ ¤ ¥ (nic) > volatile > AtomicXXX > synchronized, explicitní zámky 10/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Viditelnost a synchronizace operací Jak to dopadne? ◾ neatomičnost 64-bitového přiřazení ◾ přeuspořádání přiřazení ◾ kterákoli ze změn hodnot nemusí být viditelná ◾ jakkoli... 10.000.000 nebo 42 nebo něco jiného (neatomičnost – vlákno se může trefit mezi přiřazení horní a dolní poloviny 64 b operace) ale také může navždy cyklit (Vlakno neuvidí nastavení pripraven) pročež platí ' & $ % 1. Pokud více vláken čte jednu proměnnou, musí se řešit viditelnost. 2. Pokud více vláken zapisuje do jedné proměnné, musí se synchronizovat. § ¦ ¤ ¥ (nic) > volatile > AtomicXXX > synchronized, explicitní zámky 11/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Viditelnost a synchronizace operací volatile ◾ zajišťuje viditelnost změn mezi vlákny ◾ překladač nesmí dělat presumpce/optimalizace, které by mohly ovlivnit viditelnost ◾ u 64 b přiřazení zajišťuje atomičnost ◾ nezajišťuje atomičnost operace načti–změň–zapiš! nelze použít pro thread-safe i++ ◾ lze použít pokud jsou splněny obě následující podmínky 1. nová hodnota proměnné nezávisí na její předchozí hodnotě 2. proměnná se nevyskytuje v invariantech spolu s jinými proměnnými (např. a<=b) např. příznak ukončení nebo jiné události, který nastavuje pouze jedno vlákno – pomohlo by v příkladě třídy Nic (slajd 9) příklady použití: http://www.ibm.com/developerworks/java/library/ j-jtp06197.html ◾ pokud si nejsme jisti, použijeme raději silnější synchronizaci § ¦ ¤ ¥ (nic) > volatile > AtomicXXX > synchronized, explicitní zámky 12/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Viditelnost a synchronizace operací public class VolatileInvariant { 2 private volatile int horniMez, dolniMez; 4 public int getHorniMez() { return horniMez; } 6 public void setHorniMez(int horniMez) { if (horniMez < this.dolniMez) 8 throw new IllegalArgumentException("Horni < dolni!"); else 10 this.horniMez = horniMez; } 12 public int getDolniMez() { return dolniMez; } 14 public void setDolniMez(int dolniMez) { 16 if (dolniMez > this.horniMez) throw new IllegalArgumentException("Dolni > horni!"); 18 else this.dolniMez = dolniMez; 20 } } § ¦ ¤ ¥ (nic) > volatile > AtomicXXX > synchronized, explicitní zámky 13/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Viditelnost a synchronizace operací AtomicXXX ◾ zajišťuje viditelnost ◾ zajišťuje atomičnost operace načti–změň–zapiš nad objektem potřebujeme-li udělat více takových operací synchronně, nelze použít synchronized, explicitní zámky ◾ zajištění viditelnosti ◾ zajištění vyloučení (a tedy i atomičnosti) v kritické sekci § ¦ ¤ ¥ (nic) > volatile > AtomicXXX > synchronized, explicitní zámky 14/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Publikování a únik Publikování objektu ◾ zveřejnění odkazu na objekt ◾ thread-safe třídy nesmí publikovat objekty bez zajištěné synchronizace ◾ nepřímé publikování publikování jiného objektu, přes něhož je daný objekt dosažitelný např. publikování kolekce obsahující objekt např. instance vnitřní třídy obsahuje odkaz na vnější třídu ◾ „vetřelecké“ (alien) metody metody, jejichž chování není plně definováno samotnou třídou všechny metody, které nejsou private nebo final – mohou být přepsány v potomkovi předání objektu vetřelecké metodě = publikování objektu 15/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Publikování a únik Únik stavu objektu ◾ publikování reference na interní měnitelné (mutable) objekty ◾ v níže uvedeném příkladě může klient měnit pole states ◾ potřeba hlubokého kopírování (deep copy) 1 import java.util.Arrays; 3 public class UnikStavu { private String[] stavy = new String[]{"Stav1", "Stav2", "Stav3"}; 5 public String[] getStavySpatne() { 7 return stavy; } 9 public String[] getStavySpravne() { 11 return Arrays.copyOf(stavy, stavy.length); } 13 } 16/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Publikování a únik Únik z konstruktoru ◾ až do návratu z konstruktoru je objekt v „rozpracovaném“ stavu ◾ publikování objektu v tomto stavu je obzvláště nebezpečné ◾ pozor na skryté publikování přes this v rámci instance vnitřní třídy registrace listenerů na události 1 public class UnikZKonstruktoru { public UnikZKonstruktoru(EventSource zdroj) { 3 zdroj.registerListener( new EventListener() { 5 public void onEvent(Event e) { zpracujUdalost(e); 7 } } 9 ); } 11 } 17/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Publikování a únik Únik z konstruktoru ◾ když musíš, tak musíš... ale aspoň takto: 1. vytvořit soukromý konstruktor 2. vytvořit veřejnou factory 1 public class BezpecnyListener { private final EventListener listener; 3 private BezpecnyListener() { 5 listener = new EventListener() { public void onEvent(Event e) { 7 zpracujUdalost(e); } 9 }; } 11 public static BezpecnyListener novaInstance(EventSource zdroj) { 13 BezpecnyListener bl = new BezpecnyListener(); zdroj.registerListener(bl.listener); 15 return bl; } 17 } 18/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Thead-safe data ad hoc ◾ zodpovědnost čistě ponechaná na implementaci ◾ nepoužívá podporu jazyka ◾ pokud možno nepoužívat 19/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Thead-safe data data omezená na zásobník ◾ data na zásobníku patří pouze danému vláknu ◾ týká se lokálních proměnných u primitivních lokálních proměnných nelze získat ukazatel a tudíž je nelze publikovat mimo vlákno ukazatele na objekty je třeba hlídat (programátor), že se objekt nepublikuje a zůstává lokální lze používat ne-thread-safe objekty, ale je rozumné to dokumentovat (pro následné udržovatele kódu) 1 import java.util.Collection; 3 public class PocitejKulicky { public class Kulicka { 5 } 7 public int pocetKulicek(Collection kulicky) { int pocet = 0; 9 for (Kulicka kulicka : kulicky) { pocet++; 11 } return pocet; 13 } } 20/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Thead-safe data ThreadLocal ◾ data asociovaná s každým vláknem zvlášť, ukládá se do Thread ◾ používá se často v kombinaci se Singletony a globálními proměnnými ◾ JDBC spojení na databázi nemusí být thread-safe import java.sql.Connection; 2 import java.sql.DriverManager; import java.sql.SQLException; 4 public class PrikladTL { 6 private static ThreadLocal connectionHolder = new ThreadLocal() { 8 protected Connection initialValue() { try { 10 return DriverManager.getConnection("DB_URL"); } catch (SQLException e) { 12 return null; } 14 } }; 16 public static Connection getConnection() { 18 return connectionHolder.get(); } 20 } 21/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Thead-safe data Neměnné (immutable) objekty ◾ neměnný objekt je takový jehož stav se nemůže změnit, jakmile je zkonstruován všechny jeho pole jsou final je řádně zkonstruován (nedojde k úniku z konstruktoru) ◾ neměnné objekty jsou automaticky thread-safe ◾ pokud potřebujeme provést složenou akci atomicky, můžeme ji zabalit do vytvoření neměnného objektu na zásobníku a jeho publikaci pomocí volatile odkazu nemůžeme předpokládat atomičnost načti–změň–zapiš (i++ chování) ◾ díky levné alokaci1 nových objektů (JDK verze 5 a výš) se dají efektivně používat 1Do JDK 5.0 se používalo ThreadLocal pro recyklaci bufferů metody Integer.toString. Od verze 5.0 se vždy alokuje nový buffer, je to rychlejší. 22/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Thead-safe data Neměnné (immutable) objekty public class NemennaCache { 2 private final String lastURL; private final String lastContent; 4 public NemennaCache(String lastURL, String lastContent) { 6 this.lastURL = lastURL; this.lastContent = lastContent; 8 } 10 public String vemZCache(String url) { if (lastURL == null || !lastURL.equals(url)) 12 return null; else 14 return lastContent; } 16 } 23/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Thead-safe data Neměnné (immutable) objekty public class PouzitiCache { 2 private volatile NemennaCache cache = new NemennaCache(null, null); 4 public String nactiURL(String URL) { String obsah = cache.vemZCache(URL); 6 if (obsah == null) { obsah = fetch(URL); 8 cache = new NemennaCache(URL, obsah); return obsah; 10 } else return obsah; 12 } } 24/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Bezpečné publikování Je následující třída v pořádku? 1 public class Trida { public class Pytlicek { 3 public int hodnota; 5 public Pytlicek(int hodnota) { this.hodnota = hodnota; 7 } } 9 public Pytlicek pytlicek; 11 public void incializujPytlicek(int i) { 13 pytlicek = new Pytlicek(i); } 15 } 25/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Bezpečné publikování Nebezpečné publikování ◾ publikování potenciálně nedokončeného měnitelného objektu ◾ takto by šlo publikovat pouze neměnné objekty (lépe s použitím volatile) 1 public class NebezpecnePublikovani { public class Pytlicek { 3 public int hodnota; 5 public Pytlicek(int hodnota) { this.hodnota = hodnota; 7 } } 9 public Pytlicek pytlicek; 11 public void incializujPytlicek(int i) { 13 pytlicek = new Pytlicek(i); } 15 } 26/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Bezpečné publikování Způsoby bezpečného publikování měnitelných objektů 1. inicializace odkazu ze statického inicializátoru 2. uložení odkazu do volatile nebo AtomicReference pole 3. uložení odkazu do final pole (po návratu z konstruktoru! – obzvlášť opatrně) 4. uložení odkazu do pole, které je chráněno zámky/monitorem 5. uložení do thread-safe kolekce (Hashtable, synchronizedMap, ConcurrentMap, Vector, CopyOnWriteArray{List,Set}, synchronized{List,Set}, BlockingQueue, ConcurrentLinkedQueue) ◾ objekt i odkaz musí být publikovány současně 27/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Bezpečné publikování Efektivně neměnné objekty ◾ pokud se k objektu chováme jako neměnnému ◾ bezpečné publikování je dostatečné Měnitelné objetky ◾ bezpečné publikování zajistí pouze viditelnost ve výchozím stavu ◾ změny je třeba synchronizovat (zámky/monitory) 28/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Bezpečné sdílení objektů Uzavřené ve vlákně Sdílené jen pro čtení ◾ neměnné a efektivně neměnné objekty Thread-safe objekty ◾ zajišťují si synchronizaci uvnitř samy Chráněné objekty ◾ zabalené do thread-safe konstrukcí (thread-safe objektů, chráněny zámkem/monitorem) 29/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Ukončování vláken Vlákna by se měla zásadně ukončovat dobrovolně a samostatně ◾ metoda Thread.stop() je deprecated ◾ násilné ukončení vlákna může nechat systém v nekonzistentním stavu výjimka ThreadDeath tiše odemkne všechny monitory, které vlákno drželo objekty, které byly monitory chráněny, mohou být v nekonzistentním stavu ◾ http://java.sun.com/j2se/1.4.2/docs/guide/misc/ threadPrimitiveDeprecation.html Jak na to? ◾ zavést si proměnnou, která bude signalizovat požadavek na ukončení nebo ◾ využít příznak isInterrupted() ◾ použití metody interrupt() ◾ použití I/O blokujících omezenou dobu Vlákna lze násilně ukončovat ve speciálních případech ◾ ExecutorService ◾ Futures 30/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Ukončování vláken 1 import static java.lang.Thread.sleep; 3 public class PrikladUkonceni { static class MojeVlakno extends Thread { 5 private volatile boolean ukonciSe = false; 7 public void run() { while (!ukonciSe) { 9 try { System.out.println("...chrnim..."); 11 sleep(1000); } catch (InterruptedException e) { 13 System.out.println("Vzbudil jsem se necekane!"); } 15 } } 17 public void skonci() { 19 ukonciSe = true; } 21 } 31/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Ukončování vláken public static void main(String[] args) { 24 try { MojeVlakno vlakno = new MojeVlakno(); 26 vlakno.start(); sleep(2000); 28 vlakno.skonci(); vlakno.interrupt(); 30 vlakno.join(); } catch (InterruptedException e) { 32 e.printStackTrace(); } 34 } } 32/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol synchronized a monitory Monitory – Hoare, Dijkstra, Hansen, cca 1974 ◾ vynucuje serializovaný přístup k objektu synchronized – základní nástroj pro vyloučení v kritické sekci ◾ v Javě se označuje jako monitor ◾ synchronizuje se na explicitně uvedeném objektu (raději final) nebo (implicitně) na this ◾ Javové monitory nezahrnují podmínky, jsou jednodušší než Hoareho 33/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol synchronized a monitory 1 import net.jcip.annotations.ThreadSafe; @ThreadSafe 3 public class PrikladSynchronized { Integer cislo; 5 public PrikladSynchronized() { this.cislo = 0; 7 } public PrikladSynchronized(Integer cislo) { 9 this.cislo = cislo; } 11 void pricti(int i) { synchronized (this) { 13 cislo += i; } 15 } synchronized int kolikJeCislo() { 17 return cislo; } 19 } 34/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol synchronized a monitory Java monitor pattern 1 import net.jcip.annotations.GuardedBy; // http://www.javaconcurrencyinpractice.com/jcip-annotations.jar 3 public class MonitorPattern { 5 private final Object zamek = new Object(); @GuardedBy("zamek") Object mujObject; 7 void metoda() { 9 synchronized (zamek) { // manipulace s objektem mujObject; 11 } } 13 } 35/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Sychronized Collections Přímo synchronizované kolekce: Vector, Hashtable Synchronizované obaly: Collection.synchronizedX factory metody Tyto kolekce jsou thread-safe, ale poněkud zákeřné ◾ může být potřeba chránit pomocí zámků složené akce iterace navigace (procházení prvků v nějakém pořadí) podmíněné operace, např. vlož-pokud-chybí (put-if-absent) 36/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Sychronized Collections 1 import java.util.Vector; 3 public class PodlaKolekce { public static Object dejPosledni(Vector v) { 5 int posledni = v.size() - 1; return v.get(posledni); 7 } 9 public static void smazPosledni(Vector v) { int posledni = v.size() - 1; 11 v.remove(posledni); } 13 } 37/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Sychronized Collections 38/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Sychronized Collections Výše uvedené chování nemůže poškodit Vector v ⇒ thread-safe Chování ale bude zmatečné ◾ mezi získání indexu poslední položky a get() ev. remove() se může vloudit jiný remove() ⇒ vyhazování výjimky ArrayOutOfBoundException Lze ošetřit klientským zamykáním, pokud známe objekt, na němž se v sychronizované kolekci dělá monitor 39/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Sychronized Collections 1 import java.util.Vector; 3 public class RucneSyncnutaKolekce { public static Object dejPosledni(Vector v) { 5 synchronized (v) { int posledni = v.size() - 1; 7 return v.get(posledni); } 9 } 11 public static void smazPosledni(Vector v) { synchronized (v) { 13 int posledni = v.size() - 1; v.remove(posledni); 15 } } 17 } 40/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Signalizace mezi objekty Definováno pro každý Object Musí být vlastníkem monitoru pro daný Objekt ◾ synchronized sekce Metoda wait() ◾ usnutí do doby notifikace ◾ při usnutí se vlákno vzdá monitoru ◾ po probuzení čeká, než monitor může opět získat Metoda notify() ◾ notifikace jednoho z čekajících ◾ pokud je čekajících více, vybere se jeden (libovolně dle implementace) ◾ vybuzené vlákno pokračuje až poté, co se notifikující vlákno vzdá monitoru Metoda notifyAll() ◾ notifikace všech vláken čekajících na daném objektu 41/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Signalizace mezi objekty 42/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Suspendování vláken Metody Thread.suspend() a Thread.resume jsou inherentně nebezpečné – deadlocky Emulace pomocí wait() a notify() 43/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Suspendování vláken import static java.lang.Thread.sleep; 2 public class PrikladSuspendu { 4 static class MojeVlakno extends Thread { private volatile boolean ukonciSe = false; 6 private volatile boolean spi = false; 8 public void run() { while (!ukonciSe) { 10 System.out.println("...makam..."); try { 12 sleep(500); synchronized (this) { 14 while (spi) { wait(); 16 } } 18 } catch (InterruptedException e) { System.out.println("Necekane probuzeni!"); 20 } } 22 System.out.println("...domakal jsem..."); } 44/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Suspendování vláken 1 public void skonci() { ukonciSe = true; 3 } 5 public void usni() { spi = true; 7 } 9 public void vzbudSe() { spi = false; 11 synchronized (this) { this.notify(); 13 } } 15 } 45/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Suspendování vláken Ztracené zprávy ◾ o.wait() a o.notify() resp. o.notifyAll nemají mechanismus zdržení notifikace ◾ pokud vlákno usne na o.wait() později, než mělo být notifikováno přes o.notify, nikdy se nevzbudí ⇒ deadlock Problém při signalizaci s podmínkami ◾ odpovídá Hoareho monitorům ◾ vlákno usne do doby, než je splněna podmínka ◾ v době vzbuzení je garantováno, že je podmínka pořád splněna ◾ implementace Hoarových monitorů pro Javu: http://www.engr.mun.ca/%7Etheo/Misc/monitors/monitors.html http: //www.javaworld.com/javaworld/jw-10-2007/jw-10-monitors.html 46/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Suspendování vláken Podmíněná signalizace 47/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Suspendování vláken // podmineny predikat musi byt chraneny zamkem 2 synchronized (lock) { while (!conditionPredicate) 4 lock.wait(); // nyni je objekt v pozadovanem stavu 6 } Pravidla pro signalizaci s podmínkami 1. zformulovat a ověřit podmínku před voláním wait() 2. wait() bežet ve smyčce, kontrolovat po vzbuzení probuzení z wait() mohlo nastat z jiného důvodu 3. zajistit, aby proměnné v podmínce byly chráněny tím zámkem, který se používá v monitoru 4. držet zámek v době volání wait(), notify(), notifyAll() Potřeba zajistit, aby při změně podmínky vždy někdo zasignalizoval Signál se může ztratit, pokud bychom se vzdali mezi dalším testem monitoru 48/48 Vlákna v jazyce Java Monitory a synchronizace Signalizace a suspend Domácí úkol Domácí úkol Pomocí mechanismu signalizace naimplementujte: ◾ semafor, ◾ bariéru. Termín: 16. 3. 2014