Tråder del 2 Våren Stein Gjessing Institutt for informatikk Universitetet i Oslo

Like dokumenter
Start opp. Prosess 3 Meldingsutveksling Operativsystemet (styrer alt og sørger for kommunikasjon mellom prosesser)

Stein Gjessing. Institutt for informatikk. Universitetet i Oslo. Institutt for informatikk

INF1010 Tråder II 6. april 2016

Tråder del 2 Våren 2012

IN1010 våren Repetisjon av tråder. 15. mai 2018

INF1010 Tråder mars 2016

Invarianter, +lstander og li1 mer seman+kk

Sortering med tråder - Quicksort

Tråder Repetisjon. 9. og 13. mai Tråder

Tråder Repetisjon. 9. og 13. mai Tråder

UNIVERSITETET I OSLO

INF1010 oversikt med

IN Våren 2019 Tråder del mars 2019

Operativsystemer, prosesser og tråder

INF Våren 2017 Tråder del 1

INF1010, 22. mai Prøveeksamen (Eksamen 12. juni 2012) Stein Gjessing Inst. for Informatikk Universitetet i Oslo

INF1010 Tråder J. Marit Nybakken Motivasjon. Å lage en tråd

INF våren 2015

INF1010 Repetisjonskurs i tråder

Enkle generiske klasser i Java

INF1010 oversikt med

INF Notater. Veronika Heimsbakk 10. juni 2012

Eksamen INF1010 V2009 Del B prøveeksamen V2010 Vekt 60 %

Innhold. Introduksjon til parallelle datamaskiner. Ulike typer parallelle arkitekturer. Prinsipper for synkronisering av felles hukommelse

INF2440 Prøveeksamen, løsningsforslag, 20 mai Arne Maus PSE, Inst. for informatikk

INF1010, 15. januar time. Parametriserte klasser (generiske klasser) Stein Gjessing Inst. for Informatikk Universitetet i Oslo

La oss begynne med en repetisjon av hva som skjer når du kjører Javaprogrammet

Velkommen til. INF våren 2016

INF1010 våren januar. Objektorientering i Java

GetMutex(lock) { while(testandset(lock)) {} } En context switch kan ikke ødelegge siden testen og endringen av lock skjer i samme instruksjon.

Synkronisering II. Kapittel 7. Betingelse oppfylt (0) liste. tråd-deskriptor. venteliste. tråd-deskriptor. tråd-deskriptor.

INF1010, 21. januar Klasser med parametre = Parametriserte klasser = Generiske klasser

2 Om statiske variable/konstanter og statiske metoder.

INF Våren Li' repe$sjon om Tråder og GUI. Stein Gjessing, Ins$tu' for informa$kk, Universitetet i Oslo. Ins$tu' for informa$kk

Synkronisering I. Kapittel 6. Tråd A. ferdig. t.varsle() u.vente() Tråd B. ferdig. tid

Inf1010 oppgavesamling

IN1010 våren januar. Objektorientering i Java

UNIVERSITETET I OSLO

Avdeling for ingeniørutdanning Institutt for teknologi

INF2440 Uke 6, v2017. Arne Maus PSE, Inst. for informatikk

INF1010, 21. februar Om å gå gjennom egne beholdere (iteratorer) Stein Gjessing Inst. for Informatikk Universitetet i Oslo

UNIVERSITETET I OSLO

UNIVERSITETET I OSLO

Side 1 av 11, prosesser, tråder, synkronisering, V. Holmstedt, HiO 2006

INF2440 Uke 4, våren2014 Avsluttende om matrisemultiplikasjon og The Java Memory Model + bedre forklaring Radix. Arne Maus OMS, Inst.

INF1010 oversikt med. 19. mai Subklasser mm Unntaksbehandling GUI Tråder. Stein Gjessing InsBtuC for informabkk Universitetet i Oslo

INF2440 Uke 6, v2015 om faktorisering av primtall + tre løsninger på et produsent/konsumentproblem. Arne Maus PSE, Inst.

I et Java-program må programmøren lage og starte hver tråd som programmet bruker. Er dette korrekt? Velg ett alternativ

Kort notat om parallellstyring IN147

UNIVERSITETET I OSLO

UNIVERSITETET I OSLO

INF 1000 høsten 2011 Uke september

Forelesning III Kap 8 & 7; Dagsplan. Gjenbruk. Condition synchronization. Gjennomgående eksempler. Kode: Design: Verktøy

INF1000 undervisningen INF 1000 høsten 2011 Uke september

Inf1010 oppgavesamling

INF1010. Grensesnittet Comparable<T>

INF1010 våren 2019 Onsdag 30. januar. Mer om unntak i Java (med litt repetisjon av I/O først)

INF våren 2017

Fra Python til Java. En introduksjon til programmeringsspråkenes verden. Dag Langmyhr

IN1010. Fra Python til Java. En introduksjon til programmeringsspråkenes verden Dag Langmyhr

IN1010 våren 2018 Tirsdag 15. mai. Repetisjon av subklasser og tråder. Stein Gjessing Institutt for informatikk Universitetet i Oslo

INF2100. Oppgaver uke 40 og

INF1010 oversikt med. 23. mai Subklasser mm. Unntaksbehandling GUI Tråder. Stein Gjessing InsBtuC for informabkk Universitetet i Oslo

public static <returtype> navn_til_prosedyre(<parameter liste>) { // implementasjon av prosedyren

Innhold. Forord Det første programmet Variabler, tilordninger og uttrykk Innlesing og utskrift...49

UNIVERSITETET I OSLO

Prøveeksamen INF2440 v Arne Maus PSE, Inst. for informatikk

IN1010. Fra Python til Java. En introduksjon til programmeringsspråkenes verden Dag Langmyhr

Kapittel 8: Programutvikling

Dagens forelesning. Java 13. Rollefordeling (variant 1) Rollefordeling (variant 2) Design av større programmer : fordeling av roller.

Innhold uke 4. INF 1000 høsten 2011 Uke 4: 13. september. Deklarasjon av peker og opprettelse av arrayobjektet. Representasjon av array i Java

IN1010''1 Våren 2018 Tråder del'1. 3.'april 2018''

Litt om Javas class-filer og byte-kode

Del 3: Evaluere uttrykk

Arne Maus OMS, Inst. for informatikk

GUI («Graphical User Interface») del 2

Lenkelister. Lister og køer. Kopi av utvalgte sider fra forelesningen.

< T extends Comparable<T> > Indre klasser mm. «Det du bør ha hørt om før oblig 4»

public static <returtype> navn_til_prosedyre(<parameter liste>) { // implementasjon av prosedyren

NOTAT (pensum!) Javas klasse-filer, byte-kode og utførelse

Kapittel 9: Sortering og søking Kort versjon

1. Krav til klasseparametre 2. Om å gå gjennom egne beholdere (iteratorer) Stein Gjessing Inst. for Informatikk Universitetet i Oslo

INF1010 våren Grensesnitt

INF1000 EKSTRATILBUD. Stoff fra uke 1-5 (6) 3. oktober 2012 Siri Moe Jensen

Java RMI. Introduksjon. Markus Foss Hans-Gunnar Vold

Det finnes ingenting. som kan gjøres med interface. men som ikke kan gjøres uten

INF2100. Oppgaver 9. oktober 2012 C 100 X 10

INF1010 våren 2017 Onsdag 25. januar. Litt om unntak i Java

INF2100. Oppgaver 23. og 24. september 2010

i=0 Repetisjon: arrayer Forelesning inf Java 4 Repetisjon: nesting av løkker Repetisjon: nesting av løkker 0*0 0*2 0*3 0*1 0*4

Forelesning inf Java 4

OPPGAVE 1 OBLIGATORISKE OPPGAVER (OBLIG 1) (1) Uten å selv implementere og kjøre koden under, hva skriver koden ut til konsollen?

INF1010 Eksamenstips. Løsningsforslag prøveeksamen del 1.

INF2100. Oppgaver 6. og 11. oktober 2011 C 100 X 10

NOTAT (pensum!) Javas klasse-filer, byte-kode og utførelse. INF 5110, 10/5-2011, Stein Krogdahl

programeksempel Et større En større problemstilling Plan for forelesingen Problemstillingen (en tekstfil) inneholdt ordet "TGA"

Jentetreff INF1000 Debugging i Java

TDT4100 Objektorientert programmering

INF1000: Forelesning 7

UNIVERSITETET I OSLO

Transkript:

Tråder del 2 Våren 2008 Stein Gjessing Institutt for informatikk Universitetet i Oslo

Om parallellitet En beregning delt opp i parallell går fortere jo mer uavhengig delene er Amdahls lov: Totaltiden er tiden i parallell + tiden det tar å kommunisere / synkronisere/ gjøre felles oppgaver Tiden det tar å synkronisere er ikke parallelliserbar (hjelper ikke med flere prosessorer) total tid Start opp Synkroniser Lag resultat Parallell beregning Parallell beregning

Prosesser og tråder P1 P2 Pn P1 P2 Pm Operativsystemet (styrer alt og sørger for kommunikasjon mellom prosesser) Operativsystemet (styrer alt og sørger for kommunikasjon mellom prosesser)

Kommunikasjon mellom prosesser (og tråder) Samarbeidende prosesser sender meldinger til hverandre (brune piler, mest vanlig) eller leser og skriver i felles lager (blå piler). Tråder kommuniserer bare ved hjelp av felles data (som del av samme prosess) Prosess 1 Prosess 2 Meldingsutveksling Prosess 3 Prosess 1 Prosess 2 Prosess 3 Felles data

Kommunikasjon mellom Java prosesser: RMI: Remote Method Invocation (Norsk: Fjern metode kall) Et Java program (på en maskin) InterfaceNavn fjernpeker Dette ønsker vi å oppnå: Et annet Java program (på en annen maskin)... fjernpeker.metodenavn( );... metodenavn objekt av en klasse som implementerer InterfaceNavn Alternativt navn: RPC: Remote Procedure Call

En maskin fjernpeker RMI: Implementasjon (bak kulissene) en proxy for fjern-objektet et skjelett formidler kall og retur Ikke pensum i INF1010 En annen maskin metodenavn tjenermetode... fjernpeker.metodenavn( );... en stub for fjern-metoden Odene proxy og stub brukes ikke alltid like konsistent fjern-objekt (kan også brukes av Javaprogrammet på denne maskinen) Parametere (og returverdi) pakkes ned og sendes mellom de to maskinen (marshaling) 6

RMI: Hvordan kalle metoder i (Java )objekter på andre maskiner klient tjener Ikke pensum i INF1010 3. oppgi navn på objekt Register 4. og få tilbake peker 2. 5. bruk peker til fjernmetode-kall (Remote Method Invocation): fjernpeker.metodenavn( ); 1. registrer (bind) med navn på objektet objekt Og det eneste som er kjent på begge maskinene er Interfacet til objektet og navnet 7

CORBA, MPI CORBA (Common Object Request Broker Architecture) er en språkuavhengig måte å definere kommunikasjon mellom fjern objekter. Et IDL (Interface Definition Language) definerer grensesnittet til objektene (på samme måte som Interface i Java) En IDL kompilator oversetter til ditt valgte språk (Java, C++, C#, Smalltalk, ) Dette gjør at prosesser skrevet i forskjellige objektorienterte språk og som kjører på forskjellige (eller samme) maskin kan kommunisere. Språk som ikke er objektorienterte: Send en melding (MPI Message Passing Interface) P1 P2 P3

Repetisjon: Tråder i Java: class MinTråd extends Thread { public void run( ) { while (<mer å gjøre>) { <gjør noe>; try {sleep(<et tall, dvs. en stund>); catch (InterruptedException e) { // end while // end run //end class MinTråd run inneholder vanligvis en løkke som utføres til oppgaven er ferdig. MinTråd objekt (en tråd) start run tråden En tråd lages og startes opp slik: MinTråd tråden; tråden = new MinTråd( ); tråden.start( ); Her går den nye og den gamle tråden (dette programmet), vider hver for seg start( ) er en metode i Thread som må kalles opp for å få startet tråden. start-metoden vil igjen kalle metoden run (som vi selv programmerer). 9

Kommunikasjon mellom tråder: Felles data Felles data (blå felt) må vanligvis bare aksesseres (lese eller skrives i) av en tråd om gangen. Hvis ikke blir det kluss i dataene. Et felles objekt kalles en monitor. Metodene i en monitor har modifikatoren synchronized f.eks. F F put hent Buffer Monitor er ikke noe ord i Java Produsenter Konsumenter 10

Basale Java verktøy: synchronized, wait(), notify() og notifyall() (metodene er definert i class Object) produsenter while ( ) { <lag noe>; p.putinn(...); while ( ) { <lag noe>; p.putinn(...); synchronized void putinn( int verdi) while (full) wait(); // nå er bufferet ikke fult < legg inn> En monitor (et objekt) synchronized int hentut If (empty) return null; else <ta ut et element> // nå er bufferet ikke fult notify(); return element; konsumenter while ( ) { p.hentut <bruk dette>; while ( ) { p.hentut <bruk dette>; Pass på: polling (prøve om og om igjen uten å få gjort noe)

kø for å få låsen første gang En kø av ventende tråder på hele monitoren ventende tråder synchronized void putinn( int verdi) while (full) wait(); // nå er bufferet ikke fult < legg inn> En monitor (et objekt) synchronized int hentut If (empty) return null; else <ta ut et element> // nå er bufferet ikke fult notify(); return element; Pluss en kø av ventende tråder på wait instruksjoner (wait set). Startes av notify () og/eller notifyall()

Java har én kø for alle wait() instruksjonene på samme objekt! kø for å få låsen første gang ventende tråder produsenter while ( ) { <lag noe>; p.putinn(...); while ( ) { <lag noe>; p.putinn(...); synchronized void putinn( int verdi) while (full) wait(); // nå er bufferet ikke fult < legg inn> // nå er bufferet ikke fullt notify(); synchronized int hentut while (empty) wait(); // nå er bufferet ikke tomt <ta ut et element> // nå er bufferet ikke fult notify(); return element; konsumenter while ( ) { p.hentut <bruk dette>; while ( ) { p.hentut <bruk dette>; En monitor (et objekt) Pass på: Unngå vranglås (deadlock)

Finn minste tall i tabell (samme teknikk for å finne sum / gjennomsnitt) Hovedprogrammet starter N tråder og venter på at de alle er ferdige før det henter minste verdi fra monitoren MinstVerdi Tråd 1 finner minste tall i denne delen av tabellen Tråd 2 finner minste tall i denne delen av tabellen synchronized void giminsteverdi( int verdi) synchronized int hentminst Objekt av klassen MinstVerdi Trådenes minste verdi gis til monitoren Tråd n (64?) finner minste tall i denne delen av tabellen

Amdahls lov og finn minste tall Totaltid: Tiden det tar å lage 64 og sette i gang 64 tråder (kan det gjøres i parallell?) Tiden det tar å finne et minste tall i min del av tabellen Til slutt i monitoren: En og en tråd må teste sitt resultat (Kan det gjøre i parallell?)

Hovedprogrammet versjon 1 public class MinstR { final int maxverdiint = Integer.MAX_VALUE; int [ ] tabell; MinstMonitor monitor; public static void main(string[ ] args) { new MinstR(); public MinstR ( ) { tabell = new int[640000]; for (int in = 0; in< 640000; in++) tabell[in] = (int)math.round(math.random()* maxverdiint); monitor = new MinstMonitorR(); for (int i = 0; i< 64; i++) // Lag og start 64 tråder new MinstTradR(tabell,i*10000,((i+1)*10000)-1,monitor).start(); monitor.vent(); System.out.println("Minste verdi var: " + monitor.hentminste()); Monitor for resultater og synkronisering interface MinstMonitor { void vent(); void giminsteverdi (int minverdi); int hentminste (); class MinstMonitorR implements MinstMonitor {....

Tråder som finner minste tall i del av tabellen class MinstTradR extends Thread { int [ ] tab; int startind, endind; MinstMonitor mon; MinstTradR(int [ ] tb, int st, int en, MinstMonitor m) { tab = tb; startind = st; endind = en; mon = m; public void run(){ int minverdi = Integer.MAX_VALUE; for ( int ind = startind; ind <= endind; ind++) if(tab[ind] < minverdi) minverdi = tab[ind]; // denne tråden er ferdig med jobben: mon.giminsteverdi(minverdi); // slutt run // slutt MinstTradR

Barierer i parallellprogrammering Bariere, dvs. vent på at alle er ferdig Denne tråden kan fortsetter når alle har nådd barieren (join) Gren opp i parallell beregning (fork) Ny forgrening Alle trådene sier fra når de har nådd barieren Alle trådene avsluttes med å kalle en metode i en og samme monitor tid

Hovedprogrammet versjon med bariere import java.util.concurrent.*; public class MinstB { final int maxverdiint = Integer.MAX_VALUE; int [ ] tabell; final int antalltrader = 64; MinstMonitor monitor = new MinstMonitorB();; CountDownLatch bariere = new CountDownLatch(antallTrader); public static void main(string[ ] args) { new MinstB(); public MinstB ( ) { tabell = new int[640000]; for (int in = 0; in< 640000; in++) tabell[in] = (int)math.round(math.random()* maxverdiint); for (int i = 0; i< antalltrader; i++); // Lag og start antalltrader tråder new MinstTradB(tabell,i*10000,((i+1)*10000)-1,monitor,bariere).start(); //vent på at alle trådene er ferdig: try { bariere.await(); // vent på at alle Minst-trådene har nådd barieren System.out.println("Minste verdi var: " + monitor.hentminste() ); catch (InterruptedException ex){

class MinstMonitorB implements MinstMonitor { private int minsttilna = Integer.MAX_VALUE; Monitor for resultater void vent(){ // brukes ikke synchronized void giminsteverdi (int minverdi) { if(minsttilna > minverdi) minsttilna = minverdi; synchronized int hentminste () {return minsttilna;

Tråder som finner minste tall i del av tabellen class MinstTradB extends Thread { int [ ] tab; int startind, endind; CountDownLatch bariere; MinstMonitor mon; MinstTradB(int [ ] tb, int st, int en, MinstMonitor mon, CountDownLatch bariere) { tab = tb; startind = st; endind = en; this.mon = mon; this. bariere = bariere; public void run(){ int minverdi = Integer.MAX_VALUE; for ( int ind = startind; ind <= endind; ind++) if(tab[ind] < minverdi) minverdi = tab[ind]; // gi minste resultat til monitoren: mon.giminsteverdi(minverdi); // signaler at denne tråden er ferdig med jobben: bariere.countdown(); // sier fra at jeg har nådd barieren // slutt run // slutt MinstTradB

Barieren i dette eksempelt Start opp Gren opp i parallell beregning (fork) Alle trådene sier fra når de har nådd barieren Bariere, Denne tråden kan fortsetter når alle har nådd barieren (join). Da er det endelige resultatet klart. Alle trådene avsluttes med å kalle en metode i en og samme monitor tid

Maskinarkitektur, f.eks. 4 prosessorer prosessor registre cache 1 cache 2 prosessor registre cache 1 Minne (RAM) prosessor registre cache 1 cache 2 prosessor registre cache 1

Javas minnemodell (memory model) En minnemodel defineres ved å se på lovlige rekkefølger av lese og skriveoperasjoner på variable. Innad i en tråd skjer ting i rekkefølgen gitt av programmet, bortsett fra av at uavhengige operasjoner kan re ordnes (for optimalisering). Mellom tråder skjer ting ikke i rekkefølge untatt Ved bruk av Volatile variable Alle operasjoner før en unlock skjer i rekkefølge før alle operasjoner etter en etterfølgende lock på den samme monitoren.

Volatile variable en variabel som er deklarert volatile caches ikke (og oppbevares ikke i registre). En volatil variable skrives helt tilbake i primærlageret før neste instruksjon utføres. Rekkefølgen av skriv/les operasjoner på volatile variable og låsing/opplåsing av låser definerer en sekensielt konsistent rekkefølge av alle operasjoner som er en del av semantikken til programmeringsspråket Java

F.eks. fra definisjonen av Java: Versjon 3 side 579: 17.7 Non atomic Treatment of double and long Some implementations may find it convenient to divide a single write action on a 64 bit long or double value into two write actions on adjacent 32 bit values. For efficiency's sake, this behavior is implementation specific; Java virtual machines are free to perform writes to long and double values atomically or in two parts. For the purposes of the Java programming language memory model, a single write to a non volatile long or double value is treated as two separate writes: one to each 32 bit half. This can result in a situation where a thread sees the first 32 bits of a 64 bit value from one write, and the second 32 bits from another write. Writes and reads of volatile long and double values are always atomic. Writes to and reads of references are always atomic, regardless of whether they are implemented as 32 or 64 bit values. VM implementors are encouraged to avoid splitting their 64 bit values where possible. Programmers are encouraged to declare shared 64 bit values as volatile or synchronize their programs correctly to avoid possible complications.

Mer fra definisjonen av Java: Versjon 3 side 579: For example, in the following (broken) code fragment, assume that this.done is a non volatile boolean field: while (!this.done) Thread.sleep(1000); The compiler is free to read the field this.done just once, and reuse the cached value in each execution of the loop. This would mean that the loop would never terminate, even if another thread changed the value of this.done.

Fordelen med konstanter (immutable objects) Konstanter kan det aldri skrives til Minnemodellen for konstanter blir derfor veldig enkel. Prøv å ha mest mulig konstanter når data skal deles mellom tråder. Eksempel: Geografiske data, observasjoner Hvis du ønsker å gjøre en forandring: Kast det gamle objektet og lag et nytt.

Invarianter på data i løkker // vi vet ingenting int minsttilnaa = tabell[0]; // minsttilnaa inneholder minste verdi i området // fra og med tabell [0] til og med tabell[0] for (indeks = 1; indeks < 1000; indeks ++) { Inv(0) 0 // minsttilnaa inneholder minste verdi i området // fra og med tabell [0] til og med tabell[indeks-1] if (minsttilnaa > tabell [indeks] ) minsttilnaa = tabell[indeks] // minst TilNaa inneholder minste verdi i området // fra og med tabell [0] til og med tabell[indeks] Inv(indeks) Inv(indeks-1) // Nå er indeks == 1000 // minsttilnaa inneholder minste verdi i området // fra og med tabell [0] til og med tabell[indeks-1] // Da følger: // minsttilnaa inneholder minste verdi i området // fra og med tabell [0] til og med tabell[999]!!!!!!! Hvis Inv(indeks) er sant og vi utfører: indeks ++ så er etterpå Inv(indeks-1) sant 999

Invarianter på data i objekter Invariant: Alle dataene vi lagrer ligger i tabell[0] til og med tabell [antall 1] og -1 <= antall <= 1000 0 settinn(x) { if (antall == 1000) return ; antall ++; tabell[antall-1] = x; antall taut ( ) { if (antall == -1) return null; antall --; return (tabell[antall]); Overbevis deg (og andre) om at metodene bevarer Invarianten!!!!!!!!!!!!!!!!!!!!! 999

Hvordan bevare invarianter på data i objekter når vi ikke har ansvaret alene. Svar: Vi venter ofte på at andre skal gjøre objektets (monitorens) tilsand hyggeligere. venter på å komme inn første gang synchronized void setinn( int verdi) If (full) vent til: Ikke Full(); antall++; : notify: Ikke Tom(); synchronized int taut If (empty) vent til: Ikke Tom(); antall ; : notify: Ikke Full(); En monitor (et objekt) Invariant: Alle dataene vi lagrer ligger i tabell[0] til og med tabell [antall 1] og -1 <= antall <= 1000

Java: Flere køer av ventende tråder Lock laas = new ReentrantLock(); Condition ikkefull = laas.newcondition(); Condition ikketom = laas.newcondition(); void settinn ( int verdi) laas.lock(); try { while (full) ikkefull.await(); // nå er det helst sikkert ikke fult : // det er lagt inn noe, så det er // helt sikkert ikke tomt: ikketom.signal(); finally { ikketom.signal(); inttaut( ) En kø for selve låsen og en kø for hver condition variabel (import java.concurrent.locks.*) Metodene er ikke lenger synchronized men vi må låse (og låse opp!) monitoren selv.

Java API Interface Condition void await() Causes the current thread to wait until it is signalled or interrupted void signal() Wakes up one waiting thread.

Lock laas = new ReentrantLock(); Condition ikkefull = laas.newcondition(); Condition ikketom = laas.newcondition(); void settinn ( int verdi) throws InterrupedException laas.lock(); try { while (full) ikkefull.await(); // OK med if? // nå er det helst sikkert ikke fult : // det er lagt inn noe, så det er helt sikkert ikke tomt: ikketom.signal(); finally { laas.unlock(); inttaut( ) throws InterrupedException laas.lock(); try { while (tom) ikketom.await(); // OK med if? // nå er det helst sikkert ikke tomt; : // det er det tatt ut noe, så det er helt sikkert ikke fult: ikkefull.signal(); finally { laas.unlock(); Nå har vi en kø per betingelse som skal oppfylles Bra!

Legg merke til bruken av finally void putinn ( int verdi) throws InterrupedException { laas.lock(); try { while (full) ikkefull.await(); : : : finally { laas.unlock(); Da blir laas.unlock() alltid utført!!