Outline 0024 Spring 2010 9 :: 2 Reasoning about parallel - - PowerPoint PPT Presentation
Outline 0024 Spring 2010 9 :: 2 Reasoning about parallel - - PowerPoint PPT Presentation
Outline 0024 Spring 2010 9 :: 2 Reasoning about parallel programs 0024 Spring 2010 9 :: 3 Reasoning about parallel programs 0024 Spring 2010 9 :: 4 Example 0024 Spring 2010 9
–9 :: 2 – 0024 Spring 2010
Outline
–9 :: 3 – 0024 Spring 2010
Reasoning about parallel programs
–9 :: 4 – 0024 Spring 2010
Reasoning about parallel programs
–9 :: 5 – 0024 Spring 2010
Example
–9 :: 6 – 0024 Spring 2010
Example, continued
–9 :: 7 – 0024 Spring 2010
Updates
–9 :: 8 – 0024 Spring 2010
Updates
–9 :: 9 – 0024 Spring 2010
Slightly modified example
–9 :: 10 – 0024 Spring 2010
Slightly different updates
–9 :: 11 – 0024 Spring 2010
Example, another variation
–9 :: 12 – 0024 Spring 2010
Slightly different updates
–9 :: 13 – 0024 Spring 2010
Visibility of updates
–9 :: 14 – 0024 Spring 2010
Recall
–9 :: 15 – 0024 Spring 2010
Reasoning about programs
–9 :: 16 – 0024 Spring 2010
Correctness
–9 :: 17 – 0024 Spring 2010
(Absence of) deadlock
–9 :: 18 – 0024 Spring 2010
Deadlock
–9 :: 19 – 0024 Spring 2010
Liveness
–9 :: 20 – 0024 Spring 2010
Fairness models
–9 :: 21 – 0024 Spring 2010
Strong and weak fairness
Heres the classical example to see the difference:
Assume flag==1 if and only if (“iff”) a thread wants to
request service.
Thread A periodically issues a request, then cancels Thread B continuously issues a request Service provide checks at times t0, t1, t2
A: B:
1 1 t0 t1 t2
–9 :: 22 – 0024 Spring 2010
Synchronization
Foundation: mutual exclusion
Sequence of operations to be executed atomically called
critical section
Mutual exclusion: instructions from critical sections must
not be interleaved
Model of a program
loop { non_critical_section enter_protocol critical section exit_protocol non_critical_section }
–9 :: 23 – 0024 Spring 2010
Requirements for mutex solution
No deadlock.
If some threads attempt to execute their critical section, then
- ne of them must eventually succeed.
No starvation.
If a thread wants to enter its critical section, eventually it will
succeed.
No undue delays.
If there is no contention, a thread that wishes to enter its
critical section will succeed.
Corrollary: overhead should be small in the absence of
contention.
–9 :: 24 – 0024 Spring 2010
Notes
Thread not allowed to halt in critical section
Halt in non_critical_section not allowed to interfere with the
rest of the system
–9 :: 25 – 0024 Spring 2010
First attempt
Idea: volatile int variable that indicates which thread can proceed. Volatile assures that all threads see updates to these variables in order, i.e. if this sequence of updates is done (a, b, c volatile and initially 0) a = 1; b = 2; c = 3; then a thread that sees that c==3 will also see that a==1 and b==2. No guarantee on when a thread sees the updates, though.
–9 :: 26 – 0024 Spring 2010
First attempt: PingPong
class PingPong { public static void main(String[] args) { Turn t = new Turn(); Thread t1 = new Thread(new Worker(0,t)); Thread t2 = new Thread(new Worker(1,t)); t1.start(); t2.start(); } }
–9 :: 27 – 0024 Spring 2010
class Turn { volatile int turn = 0; } class Worker implements Runnable { private int myid; private Turn signal; Worker(int id, Turn t) { myid = id; signal = t; } public void run() { while (true) { while ( !(signal.turn == myid) ) { } signal.turn = (myid==0) ? 1 : 0; } } }
–9 :: 28 – 0024 Spring 2010
In detail
public void run() { while (true) { S1: non_critical section S2: while ( !(signal.turn == myid)){} S3: critical_section S4: signal.turn = (myid==0) ? 1 : 0; } }
–9 :: 29 – 0024 Spring 2010
Observations
Solution satisfies the mutual exclusion requirement.
Reasoning: Suppose both threads are in their critical
section (S3)
Assume that Thread A [id 0] entered first (time t1), Thread B
[id 1] at time t2 = t1 + d, and A remained in its critical section during d.
At time t1, turn == 0, so A could exit from the loop S2. At time t2, turn == 1, so B could exit from the loop S2. But during d, A remained in the critical section, so no
assignment to turn, and turn == 0.
So turn == 1 at time t2: Contradiction.
–9 :: 30 – 0024 Spring 2010
Solution cannot deadlock. There is no starvation. Solution can fail in the absence of contention.
–9 :: 31 – 0024 Spring 2010
Log
java PingPong 0 before loop 0 past loop ... 1 before loop 0.... leaving 0 before loop 1 past loop ... 1.... leaving 0 past loop ... 1 before loop 0.... leaving 0 before loop 1 past loop ... 1.... leaving 1 before loop 0 past loop ... 0.... leaving 1 past loop ... 0 before loop 1.... leaving 0 past loop ... 1 before loop 0.... leaving 1 past loop ... 0 before loop
–9 :: 32 – 0024 Spring 2010
Second attempt
Each thread has its own variable (flag)
Request0 == 0 indicates that thread w/ id 0 wants to enter its
critical section
Request0 == 1 indicates that thread w/ id 0 does not want to
enter.
Request1 == 0 …
–9 :: 33 – 0024 Spring 2010
class Turn { // 0 : wants to enter exclusive section // 1 : does not want to enter ... volatile int request0 = 1; volatile int request1 = 1; }
–9 :: 34 – 0024 Spring 2010
Worker 0
class Worker0 implements Runnable { private int myid; private Turn signal; Worker0(Turn t) { myid = 0; signal = t; } public void run() { // next slide } }
–9 :: 35 – 0024 Spring 2010
Worker 0
while (true) { while (true) { if (signal.request1 == 1) break; } signal.request0 = 0; // critical section signal.request0 = 1; }
–9 :: 36 – 0024 Spring 2010
Worker 1
public void run() { while (true) { while (true) { if (signal.request0 == 1) break; } signal.request1 = 0; // critical section signal.request1 = 1; } }
–9 :: 37 – 0024 Spring 2010
Discussion
Two threads A [id 0] and B [id 1] can be in their critical sections at the same time. Possible interleaving A checks request1, request1 == 1 B checks request0, request0 == 1 A sets request0 = 0 B sets request1 = 0 A enters critical section B enters critical section
–9 :: 38 – 0024 Spring 2010
Log
0 before loop 0 enter ... 1 before loop 0.... exit 0 before loop 1 enter ... 0 enter ... 1.... exit
–9 :: 39 – 0024 Spring 2010
Third attempt
Cant stop a thread after loop request1 (request0) set too late - must be part of the enter protocol
–9 :: 40 – 0024 Spring 2010
Third attempt
class Turn { // 0 : wants to enter exclusive section // 1 : does not want to enter ... private volatile int flag = 1; void request() { flag = 0;} void free() { flag = 1; } int read() { return flag; } }
–9 :: 41 – 0024 Spring 2010
Worker
class Worker implements Runnable { private int myid; private Turn mysignal; private Turn othersignal; Worker(int id, Turn t0, Turn t1) { myid = id; mysignal = t0;
- thersignal = t1;
}
–9 :: 42 – 0024 Spring 2010
Worker
public void run() { while (true) { mysignal.request(); while (true) { if (othersignal.read() == 1) break; } // critical section mysignal.free(); } } }
–9 :: 43 – 0024 Spring 2010
Master
class Synch3b { public static void main(String[] args) { Turn gate0 = new Turn(); Turn gate1 = new Turn(); Thread t1 = new Thread(new Worker(0,gate0, gate1)); Thread t2 = new Thread(new Worker(1,gate1, gate0)); t1.start(); t2.start(); } }
–9 :: 44 – 0024 Spring 2010
Worker
public void run() { while (true) { mysignal.request(); while (true) { if (othersignal.read() == 1) break; } // critical section mysignal.free(); } } }
–9 :: 45 – 0024 Spring 2010
Worker 0
public void run() { while (true) { A1: A2: s0.request(); A3: while (true) { if (s1.read() == 1) break; } A4: // critical section A5: s0.free(); } } }
–9 :: 46 – 0024 Spring 2010
Worker 1
public void run() { while (true) { B1: B2: s1.request(); B3: while (true) { if (s0.read() == 1) break; } B4: // critical section B5: s1.free(); } } }
–9 :: 47 – 0024 Spring 2010
Mutual exclusion
We use the notation “at(S)” to indicate that execution is “at statement (location) S”
All previous statements have executed S has not yet started to execute
Invariants s0.flag == 0 equivalent to (at(A3) V at(A4) V at(A5)) s1.flag == 0 equivalent to (at(B3) V at(B4) V at(B5))
- not (at(A4) at(B4))
V
–9 :: 48 – 0024 Spring 2010
Discussion
Satisfies mutual exclusion property. Threads can deadlock.
Thread A [id 0] assigns 0 to s0.flag Thread B [id 1] assigns 0 to s1.flag
Recall that mysignal is a local reference We use the names s0, s1 for convenience
Thread A checks s1.flag Thread B checks s0.flag
–9 :: 49 – 0024 Spring 2010
Log
0 before loop 0 enter ... S[0,1] 1 before loop 0.... exit S[0,0] 0 before loop 1 enter ... S[1,0] 1.... exit S[0,0] 1 before loop
–9 :: 50 – 0024 Spring 2010
Fourth attempt
Introduce backoff: a thread gives up its plan to enter the critical section if there is another thread.
–9 :: 51 – 0024 Spring 2010
Fourth attempt
class Turn { // 0 : wants to enter exclusive section // 1 : does not want to enter ... private volatile int flag = 1; void request() { flag = 0;} void free() { flag = 1; } int read() { return flag; } }
–9 :: 52 – 0024 Spring 2010
Worker
public void run() { while (true) { mysignal.request(); while (true) { if (othersignal.read() == 1) break; mysignal.free(); mysignal.request(); } // critical section mysignal.free(); } }
–9 :: 53 – 0024 Spring 2010
Discussion
Satisfies mutual exclusion property. Same proof as for previous attempt.
–9 :: 54 – 0024 Spring 2010
Observation
A thread can be starved. Thread A can make a “full circle” while B waits forever. (Assume same naming conventions)
Thread A: s0.flag = 0; Thread B: s1.flag = 0; B checks s0.flag, then resets s1.flag = 1 A checks s1.flag, enters critical section, exits and sets s0.flag = 0; B sets s1.flag = 0;
–9 :: 55 – 0024 Spring 2010
Livelock
No progress because no thread enters critical section -- but a (slightly) different sequence of events would allow one thread to enter the critical section.
Thread A: s0.flag = 0; Thread B: s1.flag = 0; A checks s1 and remains in the loop B checks s0 and remains in the loop A resets s0.flag = 1; B resets s1.flag = 1; Thread A: s0.flag = 0; Thread B: s1.flag = 0; A checks s1 and remains in the loop B checks s0 and remains in the loop
–9 :: 56 – 0024 Spring 2010
Dekkers solution
Combine first attempt (pingpong) and fourth attempt.
–9 :: 57 – 0024 Spring 2010
Dekker: core classes
class Insist { private volatile int winner; void setWinner(int id) { winner = id; } int getWinner() { return winner;} } class Turn { private volatile int flag = 1; private final Insist insist; Turn (Insist a) { insist = a; } // continued
–9 :: 58 – 0024 Spring 2010
Dekker: core classes, part 2
void request() { flag = 0;} void free() { flag = 1; } int read() { return flag; } void setWinner(int id) { insist.setWinner(id); } int getWinner() { return insist.getWinner(); } }
–9 :: 59 – 0024 Spring 2010
Worker
- public void run() {
int nextid; if (myid==0) {nextid = 1;} else {nextid=0;}; while (true) { mysignal.request(); while (true) { if (othersignal.read() == 1) break; if (mysignal.getWinner() == nextid) { mysignal.free(); while (true) { if (mysignal.getWinner() == myid) break; }; // other thread won 1st round mysignal.request(); } }
–9 :: 60 – 0024 Spring 2010
Worker, continued
// critical section mysignal.free(); mysignal.setWinner(nextid); } // end loop } }
–9 :: 61 – 0024 Spring 2010
Master
class Dekker { public static void main(String[] args) { Insist arbiter = new Insist(); Turn gate0 = new Turn(arbiter); Turn gate1 = new Turn(arbiter); Thread t1 = new Thread(new Worker(0,gate0,gate1)); Thread t2 = new Thread(new Worker(1,gate1,gate0)); t1.start(); t2.start(); } }
–9 :: 62 – 0024 Spring 2010