Outline 0024 Spring 2010 10 :: 2 Recall 0024 Spring 2010 10 - - PowerPoint PPT Presentation

outline
SMART_READER_LITE
LIVE PREVIEW

Outline 0024 Spring 2010 10 :: 2 Recall 0024 Spring 2010 10 - - PowerPoint PPT Presentation

Outline 0024 Spring 2010 10 :: 2 Recall 0024 Spring 2010 10 :: 3 0024 Spring 2010 10 :: 4 0024 Spring 2010 10 :: 5 Dekker: core classes class Insist { private


slide-1
SLIDE 1
slide-2
SLIDE 2

– 10 :: 2 – 0024 Spring 2010

Outline

slide-3
SLIDE 3

– 10 :: 3 – 0024 Spring 2010

Recall

slide-4
SLIDE 4

– 10 :: 4 – 0024 Spring 2010

slide-5
SLIDE 5

– 10 :: 5 – 0024 Spring 2010

slide-6
SLIDE 6

– 10 :: 6 – 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

slide-7
SLIDE 7

– 10 :: 7 – 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(); } }

slide-8
SLIDE 8

– 10 :: 8 – 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(); } }

slide-9
SLIDE 9

– 10 :: 9 – 0024 Spring 2010

Worker, continued

// critical section mysignal.free(); mysignal.setWinner(nextid); } // end loop } }

slide-10
SLIDE 10

– 10 :: 10 – 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(); } }

slide-11
SLIDE 11

– 10 :: 11 – 0024 Spring 2010

Worker 0

public void run() { while (true) { A1: s0.request(); while (true) { A2: if (s1.read() == 1) break; A3: if (s0.getWinner() == 1) { s0.free(); while (true) { if (s0.getWinner() == 0) break; }; // worker 1 won 1st round s0.request(); } // end check if worker 1 insists } A4: // critical section s0.free(); s0.setWinner(1); } // end loop } // end run

slide-12
SLIDE 12

– 10 :: 12 – 0024 Spring 2010

Worker 1

public void run() { while (true) { s1.request(); while (true) { if (s0.read() == 1) break; if (s1.getWinner() == 0) { s1.free(); while (true) { if (s1.getWinner() == 1) break; }; // worker 0 won 1st round s1.request(); } // end check if worker 0 insists } // critical section s1.free(); s1.setWinner(0); } // end loop } // end run

slide-13
SLIDE 13

– 10 :: 13 – 0024 Spring 2010

Can both threads enter the critical section?

slide-14
SLIDE 14

– 10 :: 14 – 0024 Spring 2010

slide-15
SLIDE 15

– 10 :: 15 – 0024 Spring 2010

Temporal logic

We want to show that there is no starvation. Must reason that an event (start of critical section) will happen eventually. E.g., for worker 0 we must show that once A1 is executed eventually A4 is reached

  • Must show the same for Thread B …
slide-16
SLIDE 16

– 10 :: 16 – 0024 Spring 2010

Worker 0

public void run() { while (true) { A1: s0.request(); while (true) { A2: if (s1.read() == 1) break; A3: if (s0.getWinner() == 1) { s0.free(); while (true) { if (s0.getWinner() == 0) break; }; // worker 1 won 1st round s0.request(); } // end check if worker 1 insists } A4: // critical section s0.free(); s0.setWinner(1); } // end loop } // end run

slide-17
SLIDE 17

– 10 :: 17 – 0024 Spring 2010

Notation

p means “p is always true” p means “p is eventually true” Shorthand to save us typing

slide-18
SLIDE 18

– 10 :: 18 – 0024 Spring 2010

Notation

p means “p is always true”

After p turns true we read the value “true” whenever we want

to

q means “q is eventually true”

No statement how long q will remain true.

Often we must show p

Eventually p turns true and will remain true as long as we

care to check it

Example:

p , q ⇒ ( p q )

slide-19
SLIDE 19

– 10 :: 19 – 0024 Spring 2010

Absence of starvation

slide-20
SLIDE 20

– 10 :: 20 – 0024 Spring 2010

Lemma 1

slide-21
SLIDE 21

– 10 :: 21 – 0024 Spring 2010

slide-22
SLIDE 22

– 10 :: 22 – 0024 Spring 2010

Lemma 2

slide-23
SLIDE 23

– 10 :: 23 – 0024 Spring 2010

Proof of freedom from starvation

slide-24
SLIDE 24

– 10 :: 24 – 0024 Spring 2010

Proof, continued

slide-25
SLIDE 25

– 10 :: 25 – 0024 Spring 2010

Proof, continued

slide-26
SLIDE 26

– 10 :: 26 – 0024 Spring 2010

Semaphores

Programming with critical sections is hard (impossible).

  • Better abstractions are needed.

We have seen the event queues in Java We now look at another primitive

More comfortable than critical sections based on Dekkers

solution yet still not too complicated

Idea: a semaphore S is an integer-valued variable with two operations

P(S): if S>0 then S:= S-1

else suspend thread

V(S): if (there are suspended threads) then wake one of them

else S = S+1

slide-27
SLIDE 27

– 10 :: 27 – 0024 Spring 2010

Semaphores - operations

P: wait, V: signal P(S) and V(S) are atomic

No interruption

S must be given a non-negative starting value (S0) V(S) wakes up one thread -- no way to specify which

  • ne

Binary semaphores: S is intitalized with 1

Legal values are 0 and 1

slide-28
SLIDE 28

– 10 :: 28 – 0024 Spring 2010

Semaphore invariants

i) S 0 ii) S = S0 + #V(S) - #P(S)

slide-29
SLIDE 29

– 10 :: 29 – 0024 Spring 2010

Semaphore use

Its easy to make programming mistakes: forget a V(S) and no other thread will be able to make progress

Other threads remain suspended on S forever

Model of a program

  • loop {

non_critical_section

  • P(S)
  • critical section

V(S) }

slide-30
SLIDE 30

– 10 :: 30 – 0024 Spring 2010

Properties

Mutual exclusion

Let S be a binary semaphore (i.e. S0 = 1) Proof: Let #T be the number of threads in their critical

  • sections. Show that (#T + S == 1) is invariant.

Since S 0 it follows that #T 1. Show that (#T + S == 1) is invariant:

#T == #P(S) - #V(S) S == 1 + #V(S) - #P(S) S == 1 - #T #T + S == 1

Absence of deadlock Absence of starvation of a thread

slide-31
SLIDE 31

– 10 :: 31 – 0024 Spring 2010

N threads

Solution with semaphores works for N threads

Our proof did not rely on the number of threads

Recall our different kinds of fairness - corresponding classes of semaphores

slide-32
SLIDE 32

– 10 :: 32 – 0024 Spring 2010

Semaphores

Blocked-set semaphore: (Model used so far) V(S) wakes up one of the suspended threads Blocked-queue semaphore: Suspended threads are kept in a FIFO queue, wake up in order of suspension

  • P(S): if (S >0) S-- else {append to tail of queue}

V(S): if (∃ suspended threads) {wake up thread at head of

queue, remove it from queue} else S++

Busy-wait semaphore: Value of S tested in busy wait loop (the if-stmt executes atomically but different threads may execute their if-stmt in interleaved manner)

P(S): while (true) {

if (S>0) { S=S-1; break;} }

V(S): S++

slide-33
SLIDE 33

– 10 :: 33 – 0024 Spring 2010

Properties

For a busy-wait semaphore, starvation is possible.

slide-34
SLIDE 34

– 10 :: 34 – 0024 Spring 2010

“Dining Philosophers”

N philosophers (e.g., N==5) N (5) study rooms 1 dining room 1 dining table with N (5) bowls and N (5) forks

Bowls and forks remain on table

Simple life of a philosopher:

while (true) { // think // eat }

slide-35
SLIDE 35

– 10 :: 35 – 0024 Spring 2010

Rules

A philosopher eats only if s/he has two forks

Needs those to heap pasta into the bowl Once a philosopher has a fork, s/he hangs on to it until s/he

can eat

No two philosophers may hold the same fork simultaneously Your task: organize the life of the philosophers No deadlock No individual starvation Efficient behavior (access to food) in the absence of contention

slide-36
SLIDE 36

– 10 :: 36 – 0024 Spring 2010

Dining table

slide-37
SLIDE 37

– 10 :: 37 – 0024 Spring 2010

Idea

slide-38
SLIDE 38

– 10 :: 38 – 0024 Spring 2010

Semaphore solution 1

Semaphore [] fork = new Semaphore[5]; // Default semaphore is binary // Philosopher I (0 I 4) while (true) { // think fork[i].p(); // right fork fork[mod(i+1,5)].p(); // left fork // eat fork[i].v(); fork[mod(i+1,5)].v(); }

slide-39
SLIDE 39

– 10 :: 39 – 0024 Spring 2010

Problem: Deadlock

slide-40
SLIDE 40

– 10 :: 40 – 0024 Spring 2010

Deadlock avoidance

Limit number of philosophers in dining room

additional semaphore to control room occupancy

Semaphore [] fork = new Semaphore[4]; Semaphore room = new Semaphore(4); // init to 4 // Philosopher i: while (true) { // think room.p(); fork[i].p(); fork[mod(i+1,5)].p(); // eat fork[i].v(); fork[mod(i+1,5)].v(); room.v(); }

slide-41
SLIDE 41

– 10 :: 41 – 0024 Spring 2010

Another solution

Semaphore [] fork = new Semaphore[4]; // init // Philosopher 0, 1, 2, 3: // unchanged // Philosopher 4: while (true) { // think fork[0].p(); fork[4].p(); // eat fork[4].v(); fork[0].v(); }