De presentatie wordt gedownload. Even geduld aub

De presentatie wordt gedownload. Even geduld aub

Best4-1 Les 4: Synchronisatie If debugging is the process of removing bugs, then programming must be the process of putting them in. (Edsger W. Dijkstra)

Verwante presentaties


Presentatie over: "Best4-1 Les 4: Synchronisatie If debugging is the process of removing bugs, then programming must be the process of putting them in. (Edsger W. Dijkstra)"— Transcript van de presentatie:

1 best4-1 Les 4: Synchronisatie If debugging is the process of removing bugs, then programming must be the process of putting them in. (Edsger W. Dijkstra)

2 best4-2 Overzicht Wat is synchronisatie? Software-oplossingen Hardware-oplossingen Semafoor Monitor Transactioneel geheugen Boodschappen Impasses

3 best4-3 Doelstelling Het in goede banen leiden van de interactie tussen processen of draden 1.Doorgeven van informatie 2.Vastleggen van volgorde 3.Wederzijdse uitsluiting Bij foute synchronisatie 1.Raceconditie (‘te weinig synchronisatie’) 2.Impasse (‘te veel synchronisatie’)

4 best4-4 Doorgeven van informatie B.v.: “ls | wc” Methoden: –Via bestanden, pipes, sockets –Via boodschappen (send/receive) –Via een blok gemeenschappelijk geheugen –Via kernstructuren (b.v. semaforen) Bij draden is het gebruik van gemeenschappelijk geheugen het meest voor de hand liggend

5 best4-5 Volgorde vastleggen Proces 1Proces 2 wacht signaleer tt [ [ A [ [ B A → B

6 best4-6 Wederzijdse uitsluiting Proces 1Proces 2 tt Proces 1Proces 2 tt De secties A en B zijn wederzijds uitgesloten of [ [[ [ [ [[ [ A A B B A → B B → A

7 best4-7 Gebruik van gemeenschappelijke data load r1, teller add r1, 1 store teller, r1 load r1, teller sub r1, 1 store teller, r1 tt [ [ [ [ A: teller ++ B: teller-- A → B Draad 1Draad 2 teller raceconditie

8 best4-8 Raceconditie  fout resultaat BeginVolgordeEinde teller = 10L + S L – S *teller = 10 L + L S – Steller = 9 teller = 10L + L – S Steller = 9 teller = 10L + L – S Steller = 11 teller = 10L L + S – Steller = 9 teller = 10L L + – S Steller = 9 teller = 10L L + – S Steller = 11 teller = 10L L – + S Steller = 9 teller = 10L L – + S Steller = 11 teller = 10L L – S + Steller = 11 teller = 10L L + S – Steller = 9 teller = 10L L + – S Steller = 9 teller = 10L L + – S Steller = 11 teller = 10L L – + S Steller = 9 teller = 10L L – + S Steller = 11 teller = 10L L – S + Steller = 11 teller = 10L – L + S Steller = 9 teller = 10L – L + S Steller = 11 teller = 10L – L S + Steller = 11 teller = 10L – S L + S *teller = 10 Fout Juist Proces 2Proces 1 t t Proces 2 tt [ [ [ [ [ [ [ [

9 best4-9 Raceconditie r ← var var ← 3 r = 0 ? 3 ? var ← 5var ← 3 var = 3 ? 5 ? var ← 0 leesschrijf r ← var r = 0 var ← 0 lees

10 best4-10 Kritieke Sectie

11 best4-11 Kritieke Sectie Ingangssectie Uitgangssectie load r1,teller add r1, 1 store r1,teller load r1,teller sub r1, 1 store r1,teller Ingangssectie Uitgangssectie

12 best4-12 Protocolvoorwaarden 1.wederzijdse uitsluiting garanderen slechts 1 proces per keer in een kritieke sectie 2.vooruitgang garanderen een lege sectie moet kunnen betreden worden 3.eindige wachttijden garanderen het aantal vóór te laten processen moet eindig zijn Er mogen geen veronderstellingen over snelheid of over het aantal processors gemaakt worden.

13 best4-13 Overzicht Wat is synchronisatie? Software-oplossingen Hardware-oplossingen Semafoor Monitor Transactioneel geheugen Boodschappen Impasses

14 best4-14 Oplossing met twee processen enteringCriticalSection(0) leavingCriticalSection(0) kritieke sectie 1 kritieke sectie 2 enteringCriticalSection(1) leavingCriticalSection(1) public interface MutualExclusion { public abstract void enteringCriticalSection(int turn); public abstract void leavingCriticalSection(int turn); }

15 best4-15 Beurtelings protocol public class Algorithm_1 implements MutualExclusion { private volatile int turn; public Algorithm_1() { turn = 0; } public void enteringCriticalSection(int t) { while (turn != t) Thread.yield(); } public void leavingCriticalSection(int t) { turn = 1 - t; } Geen vooruitgang gegarandeerd

16 best4-16 Hoffelijk protocol public class Algorithm_2 implements MutualExclusion { private volatile boolean flag[2]; public Algorithm 2() { flag[0] = false; flag[1] = false; } public void enteringCriticalSection(int t) { flag[t] = true; while(flag[1-t] == true) Thread.yield(); } public void leavingCriticalSection(int t) { flag[t] = false; } Geen vooruitgang gegarandeerd

17 best4-17 Algoritme van Peterson public class Algorithm_3 implements MutualExclusion { private volatile boolean flag[2]; private volatile int turn; public Algorithm 3() { flag[0] = false; flag[1] = false; turn = 1; } public void enteringCriticalSection(int t) { flag[t] = true; turn = 1-t; while (flag[1-t] == true && turn == 1-t) Thread.yield(); } public void leavingCriticalSection(int t) { flag[t] = false; } Peterson, algoritme van

18 best4-18 Overzicht Wat is synchronisatie? Software-oplossingen Hardware-oplossingen Semafoor Monitor Transactioneel geheugen Boodschappen Impasses

19 best4-19 Hardware-oplossingen Afzetten van de onderbrekingen Read-modify-write instructies –SWAP –TAS –CAS

20 best4-20 Afzetten onderbrekingen cli sti kritieke sectie 1 kritieke sectie 2 cli sti

21 best4-21 Synchronisatieprotocol met SWAP en actieve synchronisatie locked swap r1, [n] ; x := mem[n]; mem[n] := r1; r1 := x; Spin Lock LOADI R1,0 SWAP R1,locked kritieke sectie 1 kritieke sectie 2 LOADI R1,0 SWAP R1,locked LOADI R1,1 L: SWAP R1,locked COMPARE R1,1 JE L LOADI R1,1 L: SWAP R1,locked COMPARE R1,1 JE L

22 best4-22 Synchronisatieprotocol met SWAP en zonder actieve synchronisatie locked LOADI R1,0 SWAP R1,locked kritieke sectie 1 kritieke sectie 2 LOADI R1,0 SWAP R1,locked LOADI R1,1 L: SWAP R1,locked COMPARE R1,1 JNE OK “CALL YIELD” JMP L OK: LOADI R1,1 L: SWAP R1,locked COMPARE R1,1 JNE OK “CALL YIELD” JMP L OK: Gevaar op LiveLock

23 best4-23 Synchronisatieprotocol met eindige wachttijd Indien  geblokkeerde draad deblokkeer oudste draad anders LOADI R1,0 SWAP R1,locked kritieke sectie 1 kritieke sectie 2 LOADI R1,1 SWAP R1,locked COMPARE R1,1 JNE OK “store draad_id” “call blokkeer” OK: LOADI R1,1 SWAP R1,locked COMPARE R1,1 JNE OK “store draad_id” “call blokkeer” OK: Indien  geblokkeerde draad deblokkeer oudste draad anders LOADI R1,0 SWAP R1,locked

24 best4-24 Overzicht Wat is synchronisatie? Software-oplossingen Hardware-oplossingen Semafoor Monitor Transactioneel geheugen Boodschappen Impasses Edsger Wybe Dijkstra (1930– 2002)

25 best4-25 Semafoor (Dijkstra, 1965)

26 best4-26 Semafoor acquire(s) release(s) acquire(s) release(s) s=1 kritieke sectie 1 kritieke sectie 2

27 best4-27 LOADI R1,0 L: SWAP R1,sema COMPARE R1,0 JE L LOADI R1,1 STORE R1,sema kritieke sectie wederzijds uitgesloten vooruitgang geen eindige wachttijd Implementatie binaire semafoor

28 best4-28 Binaire semafoor vs. tellende semafoor Tellende semafoor (Counting semaphore) –Geïnitialiseerd met een natuurlijk getal –Acquire() decrementeert; bij 0 wordt er geblokkeerd –Release() incrementeert Binaire semafoor = tellende semafoor met initiële waarde = 1 Mutex = binaire semafoor waarbij acquire() en release() door dezelfde draad moeten gebeuren

29 best4-29 Gebruik Semaforen A A A R R R Wederzijdse uitsluiting (mutex) A A R R Wachten I I I+A D1D1 D2D2 D1D1 D2D2 D1D1 D2D2

30 Problemen met semaforen Ongestructureerd – kan leiden tot synchronisatiefouten zoals race condities en impasses. best4-30

31 best4-31 Klassieke synchronisatieproblemen Eindige buffer Lezers-schrijversprobleem Dinerende filosofen Barrier

32 best4-32 Eindige buffer met semaforen public class BoundedBuffer implements Buffer { private static final int BUFFER_SIZE = 5; private volatile Object[] buffer; private volatile int in, out; private volatile Semaphore insertmutex; private volatile Semaphore removemutex; private volatile Semaphore empty; private volatile Semaphore full;

33 best4-33 Eindige buffer met semaforen public BoundedBuffer() { // buffer is initially empty in = 0; out = 0; buffer = new Object[BUFFER_SIZE]; insertmutex = new Semaphore(1); removemutex = new Semaphore(1); empty = new Semaphore(BUFFER_SIZE); full = new Semaphore(0); } out=0 in=2 empty = 3 full = 2

34 best4-34 Eindige buffer met semaforen public void insert(Object item) { empty.acquire(); insertmutex.acquire(); // add an item to the buffer buffer[in] = item; in = (in+1) % BUFFER_SIZE; insertmutex.release(); full.release(); } public Object remove() { full.acquire(); removemutex.acquire(); // remove an item from the buffer Object item = buffer[out]; out = (out+1) % BUFFER_SIZE; removemutex.release(); empty.release(); return item; }

35 best4-35 Lezers-schrijversprobleem: Interface public interface RWLock { public abstract void acquireReadLock(); public abstract void acquireWriteLock(); public abstract void releaseReadLock(); public abstract void releaseWriteLock(); }

36 best4-36 Dinerende filosofen Semaphore chopStick[] = new Semaphore[5];

37 best4-37 Dinerende filosofen public void philosopher(int i) { while (true) { // get left chopstick chopStick[i].acquire(); // get right chopstick chopStick[(i + 1) % 5].acquire(); eating(); // return left chopstick chopStick[i].release(); // return right chopstick chopStick[(i + 1) % 5].release(); thinking(); }

38 best4-38 Barriers

39 best4-39 Overzicht Wat is synchronisatie? Software-oplossingen Hardware-oplossingen Semafoor Monitor Transactioneel geheugen Boodschappen Impasse

40 best4-40 Monitor monitor monitor-name { // variable declarations procedure p1(…) { … } procedure p2(…) { … }

41 best4-41 Monitor insert(item) Ingangssectie Uitgangssectie Ingangssectie Uitgangssectie

42 best4-42 Monitor BoundedBuffer implements Buffer { private static final int BUFFER_SIZE = 5; private volatile Object[] buffer; private volatile int in, out, count; public BoundedBuffer() { in = 0; out = 0; count = 0; buffer = new Object[BUFFER_SIZE]; } public void insert(Object item) { if (count < BUFFER_SIZE) { count++; buffer[in] = item; in = (in + 1) % BUFFER_SIZE; } else raise Exception.Create(“buffer vol”); } public Object remove() { if (count > 0) { Object item = buffer[out]; count--; out = (out + 1) % BUFFER_SIZE; return item; } else raise Exception.Create(“buffer leeg”); } In pseudo-Java stijl Eindige buffer met monitor

43 best4-43 Conditieveranderlijken condition x; x.wait() x.signal()

44 best4-44 Eindige buffer met monitor en condities Monitor BoundedBuffer implements Buffer { private static final int BUFFER_SIZE = 5; private volatile Object[] buffer; private volatile int in, out, count; private volatile Condition notempty, notfull; public BoundedBuffer() { in = 0; out = 0; count = 0; buffer = new Object[BUFFER_SIZE]; notempty = new Condition; notfull = new Condition; } public void insert(Object item) { while (count == BUFFER_SIZE) notfull.wait(); count++; buffer[in] = item; in = (in + 1) % BUFFER_SIZE; if (count == 1) notempty.signal(); } public Object remove() { Object item; while (count == 0) notempty.wait(); count--; item = buffer[out]; out = (out + 1) % BUFFER_SIZE; if (count == BUFFER_SIZE-1) notfull.signal(); return item; } In pseudo-Java stijl

45 best4-45 public class BoundedBuffer implements Buffer { private static final int BUFFER_SIZE = 5; private volatile Object[] buffer; private volatile int in, out, count; private volatile Condition notempty, notfull; private volatile Semaphore mutex; public BoundedBuffer() { in = 0; out = 0; count = 0; buffer = new Object[BUFFER_SIZE]; notempty = new Condition; notfull = new Condition; mutex = new Semaphore(1); } public void insert(Object item) { mutex.acquire(); while (count == BUFFER_SIZE) { mutex.release(); notfull.wait(); mutex.acquire(); } count++; buffer[in] = item; in = (in + 1) % BUFFER_SIZE; if (count == 1) notempty.signal(); mutex.release(); } public Object remove() { Object item; mutex.acquire(); while (count == 0) { mutex.release(); notempty.wait(); mutex.acquire(); } count--; item = buffer[out]; out = (out + 1) % BUFFER_SIZE; if (count == BUFFER_SIZE-1) notfull.signal(); mutex.release(); return item; } notfull.signal() Niet persistent Lost signal race Eindige buffer met Semaforen & condities

46 best4-46 public class BoundedBuffer implements Buffer { private static final int BUFFER_SIZE = 5; private volatile Object[] buffer; private volatile int in, out, count; private volatile Condition notempty, notfull; private volatile Semaphore mutex; public BoundedBuffer() { in = 0; out = 0; count = 0; buffer = new Object[BUFFER_SIZE]; notempty = new Condition; notfull = new Condition; mutex = new Semaphore(1); } public void insert(Object item) { mutex.acquire(); while (count == BUFFER_SIZE) notfull.wait(mutex); count++; buffer[in] = item; in = (in + 1) % BUFFER_SIZE; if (count == 1) notempty.signal; mutex.release(); } public Object remove() { Object item; mutex.acquire(); while (count == 0) notempty.wait(mutex); count--; item = buffer[out]; out = (out + 1) % BUFFER_SIZE; if (count == BUFFER_SIZE-1) notfull.signal; mutex.release(); return item; } Eindige buffer met semaforen en condities

47 best4-47 Semaforen + wait/signal acquire(s) release(s)... cond.wait(s)... acquire(s) release(s) s=1... cond.signal()...

48 best4-48 Eindige buffer met Java synchronisatie public class BoundedBuffer implements Buffer { private static final int BUFFER_SIZE = 5; private volatile int count, in, out; private volatile Object[] buffer; public BoundedBuffer() { // buffer is initially empty count = 0; in = 0; out = 0; buffer = new Object[BUFFER_SIZE]; } public synchronized void insert(Object item) { … } public synchronized Object remove() { … } } intrinsieke lock

49 best4-49 insert() met wait/notify methoden public synchronized void insert(Object item) { while (count == BUFFER_SIZE) { try { wait(); } catch (InterruptedException e) { } } ++count; buffer[in] = item; in = (in + 1) % BUFFER_SIZE; notify(); }

50 best4-50 remove() met wait/notify methoden public synchronized Object remove() { Object item; while (count == 0) { try { wait(); } catch (InterruptedException e) { } } --count; item = buffer[out]; out = (out + 1) % BUFFER_SIZE; notify(); return item; }

51 best4-51 Bloksynchronisatie Object mutexLock = new Object();... public void someMethod() { nonCriticalSection(); synchronized(mutexLock) { criticalSection(); } nonCriticalSection(); }

52 best4-52 synchronisatieprimitieven vanaf Java 1.5 Semaforen: –Semaphore sema = new Semaphore(1); Reentrant locks: –Lock Key = new ReentrantLock(); –Key.lock() –Key.unlock() Conditieveranderlijken –Condition condvar = key.newCondition(); –condvar.await() –condvar.signal()

53 Gebruik van semaforen en locks best4-53 Lock key = new ReentrantLock(); key.lock(); try { // kritieke sectie } finally { key.unlock(); } Semaphore sem = new Semaphore(1); try { sem.acquire(); try { // kritieke sectie } finally { sem.release(); } catch(InterruptedException ie) { //... } Semafoor

54 best4-54 Overzicht Wat is synchronisatie? Software-oplossingen Hardware-oplossingen Semafoor Monitor Transactioneel geheugen Boodschappen Impasses

55 best4-55 public class BoundedBuffer implements Buffer { private static final int BUFFER_SIZE = 5; private volatile Object[] buffer; private volatile int in, out, count; public BoundedBuffer() { in = 0; out = 0; count = 0; buffer = new Object[BUFFER_SIZE]; } public void insert(Object item) { atomic { if (count == BUFFER_SIZE) retry; else { count++; buffer[in] = item; in = (in + 1) % BUFFER_SIZE; } public Object remove() { Object item; atomic { if (count == 0) retry; else { count--; item = buffer[out]; out = (out + 1) % BUFFER_SIZE; } return item; } Transactioneel geheugen commit retry

56 Transactioneel geheugen best4-56 public class BoundedBuffer implements Buffer { private static final int BUFFER_SIZE = 5; private volatile Object[] buffer; private volatile int in, out, count; public BoundedBuffer() { in = 0; out = 0; count = 0; buffer = new Object[BUFFER_SIZE]; } public void insert(Object item) { atomic (count < BUFFER_SIZE) { count++; buffer[in] = item; in = (in + 1) % BUFFER_SIZE; } public Object remove() { Object item; atomic (count > 0) { count--; item = buffer[out]; out = (out + 1) % BUFFER_SIZE; } return item; }

57 best4-57 Overzicht Wat is synchronisatie? Software-oplossingen Hardware-oplossingen Semafoor Monitor Transactioneel geheugen Boodschappen Impasses

58 best4-58 Boodschappen data send(P2, “data”) receive(P1, data) P1P2

59 best4-59 Postbus data send(PB, “data”) receive(PB, data) PB P1P2

60 Boodschappencommunicatie best4-60 Buffering 0 elementen Eindig Oneindig Synchronisatie Blocking send (indien buffer vol) Non-blocking send (faalt indien vol) Blocking receive (indien buffer leeg) Non-blocking receive (faalt indien leeg)

61 Bounded buffer met boodschappen best4-61 public class BoundedBuffer implements Buffer { private static final int BUFFER_SIZE = 5; private MailBox mailbox; public BoundedBuffer() { mailbox = new MailBox(BUFFER_SIZE); } public void insert(Object item) { mailbox.send(new Message(item)); } public Object remove() { return mailbox.receive().getitem(); }

62 Voorbeelden sockets MPI RPC RMI best4-62

63 Sockets: server best4-63 import java.net.*; import java.io.*; public class DateServer { public static void main(String[] args) { try { ServerSocket sock = new ServerSocket(6013); while (true) { Socket client = sock.accept(); PrintWriter pout = new PrintWriter(client.getOutputStream(), true); pout.println(new java.util.Date().toString()); client.close(); } } catch (IOException ioe) { System.err.println(ioe);} }

64 Sockets: client best4-64 import java.net.*; import java.io.*; public class DateClient { public static void main(String[] args) throws IOException { Socket sock = null; try { sock = new Socket(" ",6013); InputStream in = sock.getInputStream(); BufferedReader bin = new BufferedReader(new InputStreamReader(in)); String line; while( (line = bin.readLine()) != null) System.out.println(line); } catch (IOException ioe) { System.err.println(ioe); } finally { sock.close(); } }}

65 RMI: server best4-65 import java.rmi.*; import java.rmi.server.UnicastRemoteObject; import java.util.Date; public class RemoteDateImpl extends UnicastRemoteObject implements RemoteDate { public RemoteDateImpl() throws RemoteException { } public Date getDate() throws RemoteException { return new Date(); } public static void main(String[] args) { try { RemoteDate dateServer = new RemoteDateImpl(); Naming.rebind("RMIDateObject", dateServer); System.out.println("RMIDateObject bound in registry"); } catch (Exception e) { System.err.println(e); }

66 RMI: client best4-66 import java.rmi.*; public class RMIClient { public static final String server = " "; public static void main(String args[]) { try { String host = "rmi://" + server + "/RMIDateObject"; RemoteDate dateServer = (RemoteDate)Naming.lookup(host); System.out.println(dateServer.getDate()); } catch (Exception e) { System.err.println(e); } }

67 best4-67 Overzicht Wat is synchronisatie? Software-oplossingen Hardware-oplossingen Semafoor Monitor Transactioneel geheugen Boodschappen Impasses

68 best4-68 Allocatie systeemmiddelen r1.acquire(); // A1 r2.acquire(); // A2 //... r2.release(); // R2 r1.release(); // R1 Draad 1Draad 2 r2.acquire(); // A2 r1.acquire(); // A1 //... r1.release(); // R1 r2.release(); // R2 r1, r2 systeemmiddelen

69 best4-69 Impasse (deadlock) Volgorderesultaat A1 A2 R1 R2 A2 A1 R1 R2OK A1 A2 a2 a1Impasse A1 A2 a1 a2Impasse A2 A1 a2 a1Impasse A2 A1 a1 a2Impasse A2 A1 R1 A1 R2 A2 R1 R2OK A2 A1 R1 R2 A1 A2 R1 R2OK 70 verwevingen van de twee draden Leidend tot 7 unieke uitvoeringen. - 3 correct - 4 impasses

70 best4-70 Impasse : vier nodige voorwaarden van (Coffman, 1971) 1.Wederzijdse uitsluiting 2.Vasthouden en wachten 3.Geen preëmptie 4.Circulair wachten

71 best4-71 P1P1 P2P2 P3P3 R1R1 R2R2 R3R3 R4R4 Allocatiegraaf zonder impasse aanvraagpijl toekenningspijl

72 best4-72 P1P1 P2P2 P3P3 R1R1 R2R2 R3R3 R4R4 lus Allocatiegraaf met impasse

73 best4-73 P1P1 P2P2 P3P3 R1R1 R2R2 R3R3 R4R4 Allocatiegraaf met impasse lus

74 best4-74 Afhandeling van een impasse 1. preventie 2. vermijding 3. detectie 4. ontkenning

75 best4-75 Ervoor zorgen dat aan één van de vier Coffmanvoorwaarden niet voldaan is Preventie Wederzijdse uitsluiting: spooling, read-write synchronisatie. Vasthouden en wachten: alle systeemmiddelen ineens alloceren of heralloceren. geen preëmptie: systeemmiddelen ontnemen of terugnemen (vooral voor CVE en geheugen). circulair wachten: in volgorde alloceren

76 best4-76 Het besturingssysteem moet ervoor zorgen niet in een onveilige toestand te belanden. Onveilige toestand = toestand van waaruit een impasse mogelijk is. De maximale hoeveelheid systeemmiddelen moet bij het begin meegedeeld worden Gekende wiskundige oplossing: bankiersalgoritme Vermijding

77 best4-77 Geen preventie of vermijding, maar een oplossing bij het optreden ervan. Impasse detectie geeft ons de lijst van processen die betrokken zijn bij een impasse. Men kan 1 of meerdere processen uit deze lus weghalen om het systeem uit de impasse te helpen. Detectie

78 best4-78 Manuele oplossing van de impasse = situatie in de meeste commerciële OS’en Ontkenning

79 best4-79


Download ppt "Best4-1 Les 4: Synchronisatie If debugging is the process of removing bugs, then programming must be the process of putting them in. (Edsger W. Dijkstra)"

Verwante presentaties


Ads door Google