Stein Gjessing, Ins$tu' for informa$kk, Universitetet i Oslo



Like dokumenter
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

INF Våren Tråder. del 1. Stein Gjessing, Ins$tu' for informa$kk, Universitetet i Oslo. Ins$tu' for informa$kk

Inf Våren 2008 Tråder del 1 Parallelle programmer og felles data. Stein Gjessing, Institutt for informatikk, Universitetet i Oslo

Oversikt. Inf Våren Parallelle programmer og felles data. Hva er parallelle programmer I I. Hva er parallelle programmer?

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

INF Våren 2016 Tråder del mars Stein Gjessing, Ins$tu' for informa$kk, Universitetet i Oslo. Ins$tu' for informa$kk

Stein Gjessing, Ins$tu' for informa$kk, Universitetet i Oslo

Stein Gjessing, Ins$tu' for informa$kk, Universitetet i Oslo

Stein Gjessing, Ins$tu' for informa$kk, Universitetet i Oslo

INF Våren 2017 Tråder del 1

Tråder i Java Parallelle programmmer og programbiter

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

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

IN Våren 2019 Tråder del mars 2019

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

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

INF1010 Tråder II 6. april 2016

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

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

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

Sortering med tråder - Quicksort

GUI («Graphical User Interface») del 2

2 Om statiske variable/konstanter og statiske metoder.

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

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

Velkommen til. INF våren 2016

INF1010 våren 2018 tirsdag 23. januar

INF Notater. Veronika Heimsbakk 10. juni 2012

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

LO191D/LC191D Videregående programmering

Avdeling for ingeniørutdanning Institutt for teknologi

TOD063 Datastrukturer og algoritmer

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

UNIVERSITETET I OSLO

Gjennomgang av eksamen H99

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

INF1010. Grafisk brukergrensesni. med Swing og awt del 2. INF Grafisk brukergrensesni4 II

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

Fra Python til Java, del 2

INF våren 2017

INF2100. Oppgaver 26. september til 1. oktober 2007

IN våren 2018 Tirsdag 16. januar

IN våren 2019 Onsdag 16. januar

INF1010 Grafisk brukergrensesni3 med Swing og awt del 1 INF1010

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

Oblig 4Hybelhus litt mer tips enn i oppgaven

UNIVERSITETET I OSLO

Enkle generiske klasser i Java

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

INF1000 Metoder. Marit Nybakken 16. februar 2004

INF1010 våren januar. Objektorientering i Java

LITT OM OPPLEGGET. INF1000 EKSTRATILBUD Stoff fra uke September 2012 Siri Moe Jensen EKSEMPLER

UNIVERSITETET I OSLO

UNIVERSITETET I OSLO

TDT4100 Objektorientert programmering

Vi lærte sist å lage vinduer. Om å lage et vindu. GUI (Graphical User Interface)-programmering. Inf GUI - del 2

1. Finn klassene (hvilke objekter er det i problemet) 1. Dataene som beskriver problemet (hvilke objekter har vi og hvor mange klasser er det?

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

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

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

UNIVERSITETET I OSLO

INF 1010, vår 2005 Løsningsforslag uke 11

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

Grafiske brukergrensesnitt med Swing og AWT

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

Grafisk Brukergrensesnitt

Stein Gjessing, Institutt for informatikk, Universitetet i Oslo

INF1010 Grafisk brukergrensesni3 (GUI) med Swing/awt. del 1

Løse reelle problemer

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

Programmeringsspråk for nybegynnere. Krav til språket. Krav til språket. Krav til språket

Definisjon av prosess

INF Uke 10. Ukesoppgaver oktober 2012

import javax.swing.*; import java.awt.*;

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

Hva er verdien til variabelen j etter at følgende kode er utført? int i, j; i = 5; j = 10; while ( i < j ) { i = i + 2; j = j - 1; }

Løse reelle problemer

2 Om statiske variable/konstanter og statiske metoder.

INF2100. Oppgaver 23. og 24. september 2010

Oblig 4 (av 4) INF1000, høsten 2012 Værdata, leveres innen 9. nov. kl

UNIVERSITETET I OSLO

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

Forkurs INF1010. Dag 1. Andreas Færøvig Olsen Tuva Kristine Thoresen

Rekursjon. (Big Java kapittel 13) Fra Urban dictionary: recursion see recursion. IN1010 uke 8 våren Dag Langmyhr

INF1010 våren 2008 Uke 4, 22. januar Arv og subklasser

Rekursjon. (Big Java kapittel 13) Fra Urban dictionary: recursion see recursion. IN1010 uke 8 våren Dag Langmyhr

GUI («Graphical User Interface») del 2

(MVC - Model, View, Control)

Konstruktører. Bruk av konstruktører når vi opererer med "enkle" klasser er ganske ukomplisert. Når vi skriver. skjer følgende:

IN1010 våren januar. Objektorientering i Java

Operativsystemer, prosesser og tråder

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

Inf1010 oppgavesamling

Tre måter å lese fra terminal. Java 4. Eksempel. Formatert utskrift til skjerm

UNIVERSITETET I OSLO

Socket og ServerSocket

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

Løsningsforslag Test 2

Eksamen i emnet INF100 Grunnkurs i programmering (Programmering I) og i emnet INF100-F Objektorientert programmering i Java I Løsningsforslag

Transkript:

INF1010 - Våren 2012 Tråder del 1 Parallelle programmer og felles data Stein Gjessing,, Universitetet i Oslo 1

2

Oversikt Hva er parallelle programmer? Hvorfor parallelle programmer? Hvordan kan de'e skje på en CPU/prosessor? Hvordan kan de'e skje med flere CPU- er/prosessorer? På engelsk: Parallel vs Concurrent compu$ng Noen begreper: Programmer, prosesser og tråder Avbrytbare (pre emp$ve) eller ikke avbrytbare (non pre emp$ve) prosesser og tråder. Tråder i Java Hvordan ny'er vi tråder Oppdaterings problemet: Sam$dig oppdatering av data Løsningen: Monitorer = Kri$ske regioner med synkroniserte metoder. 3

Hva er parallelle programmer - I På en datamaskin kan flere programmer kjøre sam$dig: Virkelig sam,dig: To programmer får på samme $dspunkt u\ørt hver sin instruksjon (må da ha flere CPU- er/prosessorer/kjerner) Engelsk: Parallel compu$ng Tilsynelatende sam,dig: Maskinen (CPU- en/prosessoren) ski_er så raskt mellom programmene at du ikke merker det (flere ganger i sekundet). Maskinen u\ører da noen få millioner instruksjoner for hvert program før den skynder seg $l neste program. Engelsk: Concurrent compu$ng: Programmene kjører ekte eller $lsynelatende sam$dig. På norsk har vi vanligvis ikke de'e skille mellom parallel og concurrent vi kaller alt parallell (parellelle programmer) eller sam$dig Uanse' om programmene går virkelig eller $lsynelatende sam$dig, må de behandles som om de går virkelig sam$dig (fordi man ikke kan forutsi når maskinen ski_er fra et program $l et annet) 4

Hva er parallelle programmer I I Administrasjonen av hvilke program som kjører, og hvordan de deler $den og kjernene mellom seg, gjøres av opera,vsystemet (Unix, Windows, Mac- OS). Opera$vsystemet er et meget stort program og er det første programmet som startes i maskinen. Det har alle $llatelser, men skrur mange av disse $llatelsene av for vanlige programmer (eks: skrive direkte $l disken eller $l alle steder i primærlageret/ram). På de fleste opera$vsystem kan flere brukere være pålogget og kjøre sine programmer sam$dig og flere uavhengige programmer kan kjøre sam$dig Datamaskinen kan ski_e rask mellom alle de ulike programmene som er i gang i datamaskinen Eks: Du kjører både et Java- program, skriver et brev i Word og får en melding Unntak: en del enkle mobiltelefoner, lesebre', ol. 5 5

Hvorfor parallelle programmer? Maskinen har mye større kapasitet enn det vi vanligvis trenger; går for det meste på tomgang. Min PC kjører vanligvis mer enn 99% av $den tomgangsprogrammet the System Idle Process Bortse' fra siste helg hvor 99,8% gikk med $l å kjøre en simulering av en transportprotokoll i Interne' En bruker trenger å kjøre flere programmer sam$dig (se film/ Skype sam$dig som du jobber.) O_e må mange ulike brukere jobbe på samme data sam$dig (eks. et bes$llingssystem med flere selgere på samme data: en kino, en flyavgang, De'e skjer på servere (tjenermaskiner) Dual- core, N- core prosessorer: Ekte parallellitet 6 6

Datamaskinarkitektur (Computer Architecture) Før: prosessor registre cache 1 cache 2 System-bus Minne (RAM) IO-bus Disk Nå, f.eks: prosessor registre cache 1 cache 2 prosessor registre cache 1 Disk System-bus Minne (RAM) IO-bus prosessor registre cache 1 cache 2 prosessor registre cache 1 7

(prosessor) Samme figur som på forrige side, men her mangler cachene Lysark stjålet fra INF2270 - Datamaskinarkitektur

Parallellprogrammering Mer i INF2140 Parallellprogrammering vil si å løse en oppgave ved hjelp av programmer (eller programbiter) som skal/kan utføres samtidig. Samarbeidende prosesser sender meldinger til hverandre (røde piler)* eller leser og skriver i felles primærlager (blå piler) (men vanligvis ikke begge deler). Prosess 1 Prosess 2 Prosess 3 Felles data * Mest vanlig 9

Opera$vsystemets oppgave (Anbefalt kurs: INF3151) Opera$vsystemet velger hver gang det kjører, blant de mange programmene som er klare $l å kjøre, hvilke som skal kjøres nå. Hver gang betyr: Det kommer noe data utenfra (tastatur, disk, ne'verk,... ) Den innebygde klokka $kker (50 ganger i sekundet) En prosess er (midler$dig) ferdig Da vekkes opera$vsystemet opp og overtar kontrollen fra (avbryter) det programmet / de programmene som kjørte. Må huske hva de avbru'e programmene var i ferd med å gjøre. Så bestemmer opera$vsystemet reqerdig hvilke program som nå skal overta og kjøre li': De med høyest prioritet må slippe $l o_est og mest Ingen må vente alt for lenge Dersom intet program ønsker å kjøre, har opera$vsystemet en egen tomgangsprosess som kan kjøre (går bare rundt i en tom løkke). 10

Programmer, prosesser og tråder Opera$vsystemet administrerer Prosesser (og et antall tråder i hver prosess) Prosesser En prosess er u\øringen av et program Er isolert fra hverandre, kan i utgangspunktet bare snakke $l opera$vsystemet Kan sende meldinger $l andre prosesser via opera$vsystemet Eier hver sin del av hukommelsen Eier hver sine filer,... Et program Startes som én prosess (kan så evt. starte andre prosesser) En tråd Er parallelle eksekveringer inne i én prosess Alle tråder i en prosess deler prosessens del av hukommelsen (ser de samme variable og programkode) Tråder er som små - prosesser inne i en vanlig stor prosess Tråder kan også gå i ekte parallell P1 P2 Operativsystemet (styrer alt) Pn 11

Hvorfor fant man på tråder? Vi har prosesser hvorfor ikke bare bruke dem? Det går greit, men li' tregt Å ski_e fra at en prosess kjører $l at en annen kjører tar omlag 20 000 instruksjoner Prosesser ble funnet på omlag 1960, tråder minst 20 år seinere. Tråder er som små prosesser inne i én prosess, og det er langt rasker å ski_e fra en tråd $l en annen tråd (kalles o_e le'vektsprosesser) Prosesser kommuniserer vanligvis via opera$vsystemet Tråder kommuniserer via felles data Ellers har tråder og prosesser omlag samme muligheter og problemer når man lager programmer Parallellprogrammering = bruke flere prosesser og/eller flere tråder for å løse en programmeringsoppgave Programmer med tråder er mye vanskeligere å skrive og teste/feilsøke enn bare én tråd i én prosess (som vi grovt se' har gjort $l nå) (INF2140) 12

Hva bruker vi tråder $l? Alle slags tunge beregninger: Vi har et program som skal betjene flere brukere (f.eks. web- sider som Facebook, Google, flybes$llinger,... ). Tolking og vising av video (animasjon), tolking av tale,.... Simuleringsmodeller: E'erape prosesser i virkeligheten for å finne ut sta$s$kk/u\alet for f.eks. køer på et motorvei, variasjoner i biologiske systemer (simulere 100 000 laks fra fødsel $l død), datane'verk, hva skjer med et olje eller gassreservoar når oljen/gassen pumpes ut, krigføring (slag med tanks og fly),... (men kvasiparallellitet er også vanlig (og enklere)) Med flere prosessorer kan programmer med tråder gå raskere ( Dual/ Quad/8/16/. - core - prosessorer). Også mulig med grafiske prosessorer Om å programmere med tråder og prosesser: Prøv å finne det som naturlig er parallelt og uavhengig i oppgaven Lag tråder eller prosesser som kommuniserer minst mulig med hverandre. Mer om de'e i del II om tråder. 13

public class Restaurant { int antbestilt; int antlaget = 0, antservert = 0; // tallerkenrertter int antkokker = 5, antservitører = 50; Restaurant(int ant) { antbestilt = ant; for (int i = 0; i < antkokker; i++) { Kokk k = new Kokk(this, "Kokk nr. " + i); k.start(); for (int i = 0; i < antservitører; i++) { Servitor s = new Servitor(this, "Servitør nr. " + i); s.start(); public static void main(string[] args) { new Restaurant(Integer.parseInt(args[0])); synchronized boolean kokkferdig() { return antlaget == antbestilt; synchronized boolean servitørferdig() { return antservert == antbestilt; synchronized boolean puttallerken(kokk k) { // Kokketråden blir eier av låsen. while (antlaget - antservert > 2) { /* så lenge det er minst 2 tallerkner * som ikke er servert, skal kokken vente. */ try { wait(); /* Kokketråden gir fra seg * låsen og sover til den * blir vekket */ catch (InterruptedException e) { // Kokketråden blir igjen eier av låsen boolean ferdig = kokkferdig(); if (!ferdig) { antlaget++; System.out.println(k.getName() + " laget nr: " + antlaget); notify(); /* Si ifra til servitøren. */ return!ferdig; synchronized boolean gettallerken(servitor s) { // Servitørtråden blir eier av låsen. while (antlaget == antservert &&!servitørferdig()) { class Kokk extends Thread { Restaurant rest; /* så lenge kokken ikke har plassert en ny tallerken. Dermed skal * servitøren vente. */ try { wait(); /* Servitørtråden gir fra seg * låsen og sover til den * blir vekket */ catch(interruptedexception e) { // Servitørtråden blir igjen eier av låsen. boolean ferdig = servitørferdig(); if (!ferdig) { antservert++; System.out.println(s.getName() + " serverer nr: " + antservert); notify(); /* si ifra til kokken */ return!ferdig; Kokk(Restaurant rest, String navn) { super(navn); // Denne tråden heter nå <navn> this.rest = rest; public void run() { while (rest.puttallerken(this)) { // levert tallerken. try { sleep((long) (1000 * Math.random())); catch (InterruptedException e) { // Kokken er ferdig class Servitor extends Thread { Restaurant rest; Servitor(Restaurant rest, String navn) { super(navn); // Denne tråden heter nå <navn> this.rest = rest; En tråd i programmet public void run() { while (rest.gettallerken(this)) { try { sleep((long) (1000 * Math.random())); catch (InterruptedException e) { // Servitøren er ferdig Tankemodell for tråder public class Restaurant { int antbestilt; int antlaget = 0, antservert = 0; // tallerkenrertter int antkokker = 5, antservitører = 50; Restaurant(int ant) { antbestilt = ant; for (int i = 0; i < antkokker; i++) { Kokk k = new Kokk(this, "Kokk nr. " + i); k.start(); for (int i = 0; i < antservitører; i++) { Servitor s = new Servitor(this, "Servitør nr. " + i); s.start(); public static void main(string[] args) { new Restaurant(Integer.parseInt(args[0])); synchronized boolean kokkferdig() { return antlaget == antbestilt; synchronized boolean servitørferdig() { return antservert == antbestilt; synchronized boolean puttallerken(kokk k) { // Kokketråden blir eier av låsen. while (antlaget - antservert > 2) { /* så lenge det er minst 2 tallerkner * som ikke er servert, skal kokken vente. */ try { wait(); /* Kokketråden gir fra seg * låsen og sover til den * blir vekket */ catch (InterruptedException e) { // Kokketråden blir igjen eier av låsen boolean ferdig = kokkferdig(); if (!ferdig) { antlaget++; System.out.println(k.getName() + " laget nr: " + antlaget); notify(); /* Si ifra til servitøren. */ return!ferdig; synchronized boolean gettallerken(servitor s) { // Servitørtråden blir eier av låsen. while (antlaget == antservert &&!servitørferdig()) { class Kokk extends Thread { Restaurant rest; /* så lenge kokken ikke har plassert en ny tallerken. Dermed skal * servitøren vente. */ try { wait(); /* Servitørtråden gir fra seg * låsen og sover til den * blir vekket */ catch(interruptedexception e) { // Servitørtråden blir igjen eier av låsen. boolean ferdig = servitørferdig(); if (!ferdig) { antservert++; System.out.println(s.getName() + " serverer nr: " + antservert); notify(); /* si ifra til kokken */ return!ferdig; Kokk(Restaurant rest, String navn) { super(navn); // Denne tråden heter nå <navn> this.rest = rest; public void run() { while (rest.puttallerken(this)) { // levert tallerken. try { sleep((long) (1000 * Math.random())); catch (InterruptedException e) { // Kokken er ferdig class Servitor extends Thread { Restaurant rest; Servitor(Restaurant rest, String navn) { super(navn); // Denne tråden heter nå <navn> To tråder this.rest = rest; i programmet public void run() { while (rest.gettallerken(this)) { try { sleep((long) (1000 * Math.random())); catch (InterruptedException e) { // Servitøren er ferdig

Tråder i Java Er innebygget i språket I ethvert program er det minst én tråd (den som starter og kjører i main) GUI kjører en egen tråd (Event Dispatch Thread, EDT) når knapper ol. ak$veres Fra en tråd kan vi starte flere andre, nye tråder En tråd starter enten som: Et objekt av en subklasse av class Thread som inneholder en metode run() som du skriver i subklassen. Slik gjør du: Lag først objektet av subklassen (new...) Kall så metoden start() i objektet (ikke laget av deg, men arvet fra Thread). start() sørger for at run(), som du selv har skrevet, vil bli kalt. Thread implementerer grensesni'et Runnable (se under) Et objekt av en klasse som også implementerer grensesni'et Runnable run() er eneste metode i grensesni'et Gi de'e objektet som parameter $l klassen Thread, og kall start( ) på de'e Thread- objektet Li' mer komplisert. Li' mer fleksibelt (kan da også være en del av et klassehierarki) 15

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 En tråd lages og startes opp slik: run inneholder vanligvis en løkke som utføres til oppgaven er ferdig. MinTråd objekt (en tråd) start run tråden MinTråd tråden; tråden = new MinTråd( ); tråden.start( ); Her går den nye og den gamle tråden (dette programmet), videre 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). 16

Det er det vi trenger å vite om tråder Nå er resten bare opp $l fantasien J MinTråd tråden; tråden = new MinTråd( ); tråden.start( ); start tråden run objekt av subklasse av Thread 17

Sove og våkne En tråd kan sove et antall milli- (og nano) sekunder; metode i Thread: sta$c void sleep (long millis) Causes the currently execu$ng thread to sleep (temporarily cease execu$on) for the specified number of milliseconds. Andre tråder slipper da $l (får kjøre) Hvis noen avbryter tråden mens den sover skjer et unntak (ikke mer om avbrudd av tråder i INF1010): try { sleep(1000); // sover e' sekund catch (InterruptedExcep$on e) { behandle uventet avbrudd 18

import java.awt.*; import java.awt.event.*; import java.io.*; class Klokke { public static void main(string[] args) throws IOException { System.out.println("Trykk [ENTER] for å starte / stoppe"); Scanner tastatur= new Scanner (System.in); tastatur.next(); En Stoppeklokke, subklasse av Thread, inneholder : public void run() Den som lager objektet, kaller start() som igjen kaller run(). // Her lages stoppeklokke-objektet: Stoppeklokke stoppeklokke = new Stoppeklokke(); // og her settes den nye tråden i gang. stoppeklokke.start(); tastatur.next(); stoppeklokke.avslutt(); class Stoppeklokke extends Thread { private volatile boolean stopp = false; // blir kalt opp av superklassens start-metode. public void run() { int tid = 0; while (!stopp) { System.out.println(tid++); try { Thread.sleep(1 * 1000); // ett sekund catch (InterruptedException e) { System.out.println( ERROR ); System.exit(1); public void avslutt() { stopp = true;

Avbrytbare eller ikke- avbrytbare prosesser og tråder. Hvis en prosess (eller en tråd) prøver å gjøre en så lang beregning at andre prosesser (tråder) ikke slipper $l, må den kanskje avbrytes. Alle skikkelige opera$vsystemer (Windows, MAC OS og Unix/linux) greier å avbryte både prosesser og tråder f.eks. vha. klokka som sender avbruddssignal 50 ganger per sek. Gamle/enkle opera$vsystemer greide ikke det Og kanskje fremdeles ikke noen enkle mobiltelefoner/lesebre' i dag? Java- definisjonen sier at det er opp $l hver implementasjon av kjøresystemet java om tråder skal være avbrytbare eller ikke. Selv om vi har mange- core prosessorer vil en tråd ikke gjøre fornu_ig arbeid hele $de. Vi bør ha 2 8 ganger så mange tråder som prosessorer ( core- er ), avhengig av hvor mye hver tråd trenger å vente (på andre tråder eller I/O) 20

Tråder kan avbryte seg selv Vanligvis vil operativsystemet dele prosessoren mellom alle aktive tråder (tidsdeling - time-slicing ), og altså kaste en tråd ut av prosessoren etter en tid (på engelsk: pre-emption). run-metoden kan eksplisit la andre tråder slippe til ved å si yield( ); Noen ganger det kan være ønskelig å la andre aktiviteter komme foran. yield( ); slipper andre tråder til, og lar tråden som utfører yield vente midlertidig (men denne tråden blir igjen startet opp når det på ny er den sin tur). run En tråd (Et tråd-objekt) start while (!done) { : : sleep(500); : : yield ( ); : Sove og Vike 21

Tre trafikklys styrt av tre tråder Laget av Judy Bishop i læreboka Java Gently Men inni er det ingen ting 22

Her er masse felles datastruktur og metoder for å tegne opp rammen rundt lysene og knappene nederst. main JFrame f = new Traffic(); f Traffic3- klassedatastruktur class SetOfLights er en indre klasse i class Traffic3 actionperformed if (event == newsetbutton) { lights[nlights] = new SetOfLights(area, lightsposition); lights[nlights].start();.... SetOfLights[] lights = new SetOfLights[3]; 0 1 2 SetOfLights objekt (en tråd) start run while (true) <tegn lys> SetOfLights objekt (en tråd) start run while (true) <tegn lys> SetOfLights objekt (en tråd) start run 23 while (true) <tegn lys> Traffic3- objekt

import java.awt.*; import java.awt.event.*; public class Traffic3 extends JFrame implements ActionListener, ItemListener { private JPanel area; private int lightsposition = 105; private static final int lightswidth = 150; private SetOfLights[] lights = new SetOfLights[3]; private int nlights = 0, setwanted = 0; private JTextField duration; private JComboBox colours; private int light; private JButton newsetbutton; private JButton walkbutton; private JButton closebutton; Alle data er skjult for omverdenen public Traffic3() { super("traffic Lights version 3 "); getcontentpane().add("north",new Label ("Savanna Traffic Light Simulation",Label.CENTER)); area = new JPanel(); area.addmouselistener(new MouseEvtHandler()); getcontentpane().add("center",area); JPanel buttons = new JPanel(); newsetbutton = new JButton("New Set"); newsetbutton.addactionlistener(this); buttons.add(newsetbutton); colours = new JComboBox (); colours.additem("red"); colours.additem("green"); colours.additem("yellow"); colours.additem("walk"); colours.seteditable(false); colours.additemlistener(this); light = 0; buttons.add(colours); buttons.add(new JLabel("Duration")); duration = new JTextField("", 4); duration.addactionlistener(this); buttons.add(duration); walkbutton = new JButton("Walk"); walkbutton.addactionlistener(this); buttons.add(walkbutton); closebutton = new JButton("Close"); closebutton.addactionlistener(this); buttons.add(closebutton); getcontentpane().add("south",buttons); 24 Et eget objekt som tar seg av museklikk

public void itemstatechanged(itemevent e) { String s = (String) e.getitem(); if (s.equals("red")) {light = 0; else if (s.equals("green")) {light = 1; else if (s.equals("yellow")) {light = 2; else if (s.equals("walk")) {light = 3; class MouseEvtHandler extends MouseAdapter { public void mousepressed(mouseevent e) { int n = e.getx() / lightswidth; if (n < nlights) setwanted = n; En egen klasse som tar seg av museklikk public static void main(string[] args) { JFrame f = new Traffic3(); f.setsize(450, 210); f.setvisible(true); f.addwindowlistener(new WindowAdapter () { public void windowclosing(windowevent e) { System.exit(0); ); // slutt main En annen måte å sørge for at programmet terminerer normalt Sett den fargen som skal forandres Nytt lys Max tre lys Lyttemetoden ligger i hoved-objektet: public void actionperformed(actionevent e) { Object event = e.getsource(); if (event == newsetbutton) { lights[nlights] = new SetOfLights(area, lightsposition); lights[nlights].start(); lightsposition += lightswidth; nlights++; if (nlights = = 3) newsetbutton.setenabled(false); else if (event = = walkbutton) { lights[setwanted].walk = true; else if (event = = duration) { lights[setwanted].time[light]= Integer.parseInt(duration.getText()); else if (event = = closebutton) { for (int i = 0; i<nlights; i++) lights[i].stop(); setvisible(false); dispose(); System.exit(0); // slutt actionperformed 25

Trådene class SetOfLights extends Thread { private int red = 0; private JPanel area; private int x; private int light; boolean walk = false; boolean walkon = false; int time [] = {500, 500, 500, 500; Tråden(e)s tilstand Konstruere en tråd: public SetOfLights(JPanel c, int x) { area = c; this.x = x; Selve tråden(e) public void run( ) { while (true) { for (int light = 0; light < 3; light++) { if (light == red & walk) { walkon = false; for (int i = 0; i < 11; i++) { draw(light); try { sleep(time[3]); catch (InterruptedException e) { walkon =!walkon; walk = false; else { draw(light); try { sleep(time[light]); catch (InterruptedException e) { // slutt while (true) // slutt run 26

Grønn void draw(int light) { Graphics g = area.getgraphics(); g.setcolor(color.black); g.drawoval(x-8, 10, 30, 68); g.setcolor(color.cyan); g.fillrect(x-90,10,70,100); g.setcolor(color.black); g.drawstring(""+time[0], x-70, 28); g.drawstring(""+time[2], x-70, 48); g.drawstring(""+time[1], x-70, 68); g.drawstring(""+time[3], x-70, 98); switch (light) { case 0: g.setcolor(color.red); g.filloval(x, 15, 15, 15); g.setcolor(color.lightgray); g.filloval(x, 35, 15, 15); g.filloval(x, 55, 15, 15); break; case 1: g.setcolor(color.green); g.filloval(x, 55, 15, 15); g.setcolor(color.lightgray); g.filloval(x, 15, 15, 15); g.filloval(x, 35, 15, 15); break; Rød Gul Her tegner tråden ut sitt lys variablen light styrer uttegningen case 2: g.setcolor(color.yellow); g.filloval(x, 35, 15, 15); g.setcolor(color.lightgray); g.filloval(x, 15, 15, 15); g.filloval(x, 55, 15, 15); break; // slutt case if (light == red & walk) { if (walkon) g.setcolor(color.green); else g.setcolor(color.white); g.filloval(x+1, 85, 14, 14); else { g.setcolor(color.black); g.drawoval(x, 85, 15, 15); // slutt draw // slutt tråd-klassen SetOfLights // slutt class Traffic3 27

NYTT OG VIKTIG: Oppdateringsproblemet: Sam,dig oppdatering av felles data Løsningen: Kri$ske regioner med synkroniserte metoder. Først: Mer intro og aller enkleste eksempel Så et større program (Kokk og servitør) Ekstrastoff: Et program som feiler: Flysalg.java Dere'er et program som er rik$g: Flysalg2.java 28 28

Felles data Felles data (grønne felt) må vanligvis bare aksesseres (lese og skrives i) av en tråd om gangen. Hvis ikke blir det kluss i dataene. På figuren vår er det to områder vi har problemer med (dvs. at to eller flere tråder kan risikere å manipulere data i disse områdene samtidig). Disse to områdene er markert med F (for Felles). Et slikt område kalles en monitor. F Prosess k F De andre to områdene inneholder data som vi vet at bare en tråd om gangen bruker. Slikt resonement er imidlertid farlige og ofte feilaktig, derfor er det ofte best å beskytte alle delte data som om de kan bli oppdatert samtidig. Eneste unntak er data som bare leses av alle ( immutable ). Monitor er ikke noe ord i Java 29

Enkelt eksempel på at to tråder kan ødelegge felles data. Felles data: Tråden Ta: Tråden Gi: int penger = 2000; int x; felles int x; felles x = felles.penger; x -= 500 ; felles.penger = x; La oss se hva som skjer hvis tråden Ta først utføres litt, og stopper opp ved pilen. Deretter overtar tråden Gi, og hele denne tråden utføres ferdig. Til slutt utføres resten av tråden Ta. x = felles.penger; x += 500 ; felles.penger = x; Hva med ekte parallellitet? 30

Felles data: int penger = 2000; Samme med metoder Tråden Ta: Tråden Gi: void ta( ) int x; x = penger; x -= 500 ; penger = x; void gi( ) int x; x = felles.penger; x += 500 ; felles.penger = x;... felles.ta( )... felles felles... felles.gi( )... Trådene utfører metodene ta og gi som om koden inne i metodene var en del av trådenes kode. På samme måte som på forrige side kan vi se hva som skjer hvis tråden Ta først utfører metoden ta litt, og så stopper opp ved pilen. Deretter overtar tråden Gi, og hele denne tråden utføres ferdig (og utfører hele metoden gi). Til slutt utføres resten av tråden Ta (metoden ta). 31

Vi ordner dette med kritiske regioner / synkroniserte metoder. Felles data: Tråden Ta: Tråden Gi: int penger = 2000; synchronized void ta (int ant) felles felles.ta(500); felles felles.gi(500); int x; x = penger; x -= ant ; penger = x; synchronized void gi (int ant) int x; x = penger; x += ant ; penger = x; En kritisk region er en kodebit som utføres ferdig før en annen tråd får lov å utføre en kritisk region (med hensyn på de samme dataene). Max en tråd om gangen eier objektet (dataene, monitoren). Metodene i et objekt blir kritiske regioner når det står synchronized foran metodenavnene. Høyst én kritisk region kan utføres inne i et objekt om gangen. Derfor blir den felles datastrukturen inne i objektet beskyttet, og riktig oppdatert (hvis metodene er riktig programmert). Innkapsling 32

Mer om synkroniserte metoder / kri$ske regioner / monitorer Alle tråder har felles adresserom Hvis flere tråder forsøker sam$dig å først lese en variabel a så oppdatere (endre) a basert på den verdien den leste, kan det gå galt (jfr. eksemplet side 30-32) FORDI: En tråd X kan først lese verdien av a, og så bli avbru'. Så kan andre tråder Y, Z komme inn og endre a Når X igjen får kjøre, vil den oppdatere a ut fra a s gamle verdi, og ikke det den nå er Vi må besky'e slik lesing og e'erfølgende skriving av samme data Se'er vi synchronized foran metodene, vil vi sikre at: Høyst en tråd er inne i noen av de synkroniserte metodene i de'e objektet sam$dig. De'e er monitorens (objektets) eier. En tråd får slippe $l, de andre trådene må vente Når den ene er ferdig, slipper de som venter $l (en e'er en) Alle data i objektet blir skrevet skikkelig ned i variablene i RAM 33

Et større li' større eksempel kokk og servitør Kokken lager mat og se'er en og en tallerken på et bord Servitøren tar en og en tallerken fra bordet og serverer Kokken må ikke se'e mer enn BORD_KAPASITET tallerkener på bordet (maten blir kald) Servitøren kan selvsagt ikke servere mat som ikke er laget (bordet er tomt) Her: en kokk og en servitør Oppgave: lag flere av hver. 34

wait(); no$fy(); Kokken må vente når det allerede er fire tallerkener på bordet Servitøren må vente når det ikke er laget noe mat (ingen tallerkener på bordet) Kokken må starte opp kelneren igjen når han har sa' tallerken nr. 1 på bordet (eller all$d når han har sa' en tallerken på bordet?) Servitøren må starte opp kokken igjen når han tar tallerken nr. 4 fra bordet (eller all$d når han tar en tallerken fra bordet?) Kokk settallerken (vent hvis fult) henttallerken (vent hvis tomt) Servitør bord Kokk: Servitør: wait(); wait(); notify(); notify(); 35

Tror du at programmet nedenfor er feil? Hvis ja: Påvis en kjøring som gir en feilsituasjon Tror du dette programmet er riktig? Hvis ja: Begrunn hvorfor det er riktig? public class RestaurantS { RestaurantS(String[] args) { int antall = Integer.parseInt(args[0]); // antall porsjoner FellesBord bord = new FellesBord(); Kokk kokk = new Kokk(bord,antall); kokk.start(); Servitor servitor = new Servitor(bord,antall); servitor.start(); public static void main(string[] args) { new RestaurantS(args); Dette er en versjon av tilsvarende program i Rett på Java, men dette programmet er bedre (fordi bordet er skilt ut som en monitor)

class FellesBord { // en monitor private int antallpabordet = 0; // invarianten gjelder private final int BORD_KAPASITET = 4; /* Invariant: 0 <= antallpabordet <= BORD_KAPASITET */ synchronized void setttallerken() { while (antallpabordet >= BORD_KAPASITET) { /* Så lenge det allerede er BORD_KAPASITET tallerkner på bordet er det ikke lov å sette på flere. */ try { wait(); catch (InterruptedException e) { // Nå er antallpabordet < BORD_KAPASITET antallpabordet++; // bevarer invarianten System.out.println("Antall på bordet: " + antallpabordet); notify(); // Si fra til den som henter tallerkener synchronized void henttallerken() { while (antallpabordet == 0) { /* Så lenge det ikke er noen talerkener pâ bordet er det ikke lov  ta en */ try { wait(); catch (InterruptedException e) { // Nå er antallpabordet > 0 antallpabordet --; // bevarer invarianten notify(); // si fra til den som setter på tallerkener 4/9/12 37

class Kokk extends Thread { private FellesBord bord; private final int ANTALL; private int laget = 0; Kokk(FellesBord bord, int ant) { this.bord = bord; ANTALL = ant; public void run() { while(antall!= laget) { laget ++; System.out.println("Kokken lager tallerken nr: " + laget); bord.setttallerken(); // lag og lever tallerken try { sleep((long) (1000 * Math.random())); catch (InterruptedException e) { // Kokken er ferdig class Servitor extends Thread { private FellesBord bord; private final int ANTALL; private int servert = 0; Servitor(FellesBord bord, int ant) { this.bord = bord; ANTALL = ant; public void run() { while (ANTALL!= servert) { bord.henttallerken(); /* hent tallerken og server */ servert++; System.out.println("Servitør serverer nr:" + servert); try { sleep((long) (1000 * Math.random())); catch (InterruptedException e) { // Servitøren er ferdig 4/9/12 38

class Flysalg { static int antseter = 7; int antsolgt = 0; Ekstrastoff: Eksempel som feiler: public static void main(string[] args) { System.out.println("Skal selge::" + antseter + " flyseter med 2 selgere"); Flysalg fly= new Flysalg(); Selger s1 = new Selger ( Stein ", fly); s1.start(); Selger s2 = new Selger( Michael", fly); s2.start(); int antigjen () { return antseter; void selg(int ant ) { antseter -= ant; antsolgt +=ant; System.out.println(" Salg: ant igjen:" + antseter +", ant solgt: " + antsolgt);

class Selger extends Thread { Flysalg fly; String navn; Selger(String navn,flysalg fly) { this.navn = navn; this.fly = fly; public void run() { while (fly.antigjen() > 0 ) { int ønske = (int) (Math.random() * fly.antigjen() + 1); System.out.println( navn+ " vil selge:" + ønske); try { // vent litt sleep((long) (1000 * Math.random())); catch (InterruptedException e) { fly.selg(ønske); Skal selge::7 flyseter med 2 selgere Stein vil selge:2 Michael vil selge:4 Salg: ant igjen:3, ant solgt: 4 Salg: ant igjen:1, ant solgt: 6 Stein vil selge:1 Michael vil selge:1 Salg: ant igjen: 0, ant solgt: 7 Salg: ant igjen: -1, ant solgt: 8 Press any key to continue... try { sleep((long) 2000); // vent 2 sek catch (InterruptedException e) { // Selgere ferdig

class Flysalg2 { static int antseter = 7 ; int antsolgt=0; Bedre: public static void main(string[] args) { System.out.println("Skal selge::" + antseter + " flyseter med 2 selgere"); Flysalg2 fly= new Flysalg2(); Selger s1 = new Selger ( Stein ", fly); s1.start(); Selger s2 = new Selger( Michael", fly); s2.start(); int antigjen () { return antseter; synchronized boolean prøvsalg(int ant) { if (antseter >= ant ) { antseter -= ant; antsolgt += ant; System.out.println(" Salg: ant igjen:" + antseter + ", ant solgt: " + antsolgt); return true; else { return false;

class Selger extends Thread { Flysalg fly; String navn; Selger(String navn,flysalg fly) { this.navn = navn; this.fly = fly; public void run() { while (fly.antigjen() > 0 ) { Skal selge::7 flyseter med 2 selgere Stein vil selge:6 Michael vil selge:5 Salg:5, ant igjen:2, ant solgt: 5 Salget OK for:michael Allerede solgt for Stein Michael vil selge:2 Stein vil selge:2 Salg:2, ant igjen:0, ant solgt: 7 Salget OK for:stein Allerede solgt for Michael Press any key to continue... int ønske = (int) (Math.random() * fly.antigjen() +1); System.out.println( navn+ " vil selge:" + ønske); try { // vent litt sleep((long) (1000 * Math.random())); catch (InterruptedException e) { if ( fly.prøvsalg(ønske)) System.out.println("Salget OK for:" + navn); else System.out.println("Allerede solgt for " + navn);); try { sleep((long) 2000); // vent 2 sek catch (InterruptedException e) { // Selgere ferdig