1 thursday, june 22, 2006 "i think i've got the hang of it now.... :w :q :wq :wq! ^d x...

48
1 Thursday, June 22, 2006 "I think I've got the hang of it now .... :w :q :wq :wq! ^d X exit ^X^C ~. ^[x X Q :quitbye CtrlAltDel ~~q :~q logout save/quit :!QUIT ^[zz ^[ZZ ZZZZ ^H ^@ ^L ^[c $q ^# ^E ^X ^I ^T ? help helpquit ^D ^d ^C ^c help ^]q exit ?Quit ?q \qy \xyy F.M.H.! YMHAOS [email protected] KA9AHQ " - Ed Wright (0x0E2 UNIX The saga Never Ends)

Post on 20-Dec-2015

215 views

Category:

Documents


0 download

TRANSCRIPT

1

Thursday, June 22, 2006

"I think I've got the hang of it now .... :w :q :wq :wq! ^d X exit ^X^C ~. ^[x X

Q :quitbye CtrlAltDel ~~q :~q logout save/quit :!QUIT ^[zz ^[ZZ ZZZZ ^H ^@ ^L ^[c $q ^# ^E ^X ^I ^T ? help helpquit

^D ^d ^C ^c help ^]q exit ?Quit ?q \qy \xyy F.M.H.! YMHAOS [email protected]

KA9AHQ "

- Ed Wright (0x0E2 UNIX The saga Never Ends)

2

Wait and Signal Example

P1:

SWait();

SWait();

SSignal();

SSignal();

P2:SWait();SSignal();

3

Wait and Signal Example

P1: SWait();

P2: SWait();

P1: SWait();

P2: SSignal();

P1: SSignal();

P1: SSignal();

Value Queue P1 P2

2 empty execute execute

4

Wait and Signal Example

P1: SWait();

P2: SWait();

P1: SWait();

P2: SSignal();

P1: SSignal();

P1: SSignal();

Value Queue P1 P2

2 empty Block Block

1 Y N N

0 Y N N

-1 P1 Y N

0 Y N N

1 Y N N

2 Y N N

5

Can implement thread join (or Unix system call waitpid) with semaphores

Semaphore S=0;

Thread::Join

SWait();

Thread::FinishSSignal();

6

Semaphores can be used for three purposes:

To ensure mutual exclusion of a critical section (as locks)

To control access to a shared pool of resources (using counting semaphore)

To cause a thread/process to wait for a specific action to be signaled by another thread/process

7

Reader Processwait(mutex);readcount++;if (readcount == 1)

wait(wrt);signal(mutex);

…reading is performed

…wait(mutex);readcount--;if (readcount == 0)

signal(wrt);signal(mutex);

A couple of questions:

1. If a wrier is in Critical section and two readers arrive, where does the first one block and where does the second one block?

2. Why do we use a single mutex here?

8

Dining-Philosophers ProblemThere are 5 philosophers sitting at a round table.

Between each adjacent pair of philosophers is a chopstick. In other words, there are five chopsticks.

Each philosopher does two things: think and eat. The philosopher thinks for a while, and then

stops thinking and becomes hungry. When the philosopher becomes hungry, he/she

cannot eat until he/she owns the chopsticks to his/her left and right.

When the philosopher is done eating he/she puts down the chopsticks and begins thinking again.

9

Dining-Philosophers Problem

Shared data

semaphore chopstick[5];

Initially all values are 1

Allocate several resources among processes in deadlock-free, starvation-free manner

10

The philosophers basically go through the following steps.

while(1) { think for a random number of seconds

pickup forks;

eat for a random number of seconds

putdown forks;

}

11

Dining-Philosophers Problem Philosopher i:

do {wait(chopstick[i])wait(chopstick[(i+1) % 5])

…eat …

signal(chopstick[i]);signal(chopstick[(i+1) % 5]);

…think …

} while (1);

12

Dining Philosopher - Deadlock Free Solution

state[] array is initialized to THINKING

semaphore array s[i], i=0 … N-1, is initialized to zero

13

Dining Philosopher - Deadlock Free Solution

14

Dining Philosopher - Deadlock Free Solution

void take_forks(int i) {

wait(mutex);

state[i]=HUNGRY;

test(i);

signal(mutex);

wait(s[i]);

}

15

Dining Philosopher - Deadlock Free Solution

void test(i)

{ // i is philosopher number

if (state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] != EATING)

{

state[i]=EATING;

signal (s[i]);

}

}

16

Dining Philosopher - Deadlock Free Solution

void put_forks(i)

{

wait(mutex);

state[i]=THINKING;

test(LEFT);

test(RIGHT);

signal(mutex);

}

17

Sleeping Barber Problem

18

Sleeping Barber Problem

Barber shop has one barber and n chairs

If no customers are present, the barber sleeps

When customer arrives, he has to wake up the sleeping barber

If additional customer arrives while the barber is cutting another’s hair then:

• he sits down and waits if empty chairs available

• he leaves if all chairs are full

19

Sleeping Barber Problem

Customer

/*check if chair available, if not leave*/

/**signal that I have arrived**/

/*wait until barber cuts my hair */

}

Barber

/*sleep until customer wakes me up*/

/* service customer (remember to update chairs available) */

/* tell customer to leave*/

/*repeat the above for other customers*/

20

Sleeping Barber Problem

N = 5; //number of chairs

int chairs_occupied = 0;

semaphore mutex = 1;

21

Sleeping Barber Problem

N = 5; //number of chairs

int chairs_occupied = 0;

semaphore mutex = 1;

semaphore barber_finished = 0;

semaphore customer_arrived = 0;

22

Sleeping Barber Problem

Customer{

wait(mutex);

if (chairs_occupied<num)

chairs_occupied ++;

else{

signal(mutex);

exit(); }

signal(mutex);

signal(customer_arrived)

wait(barber_finished);

}

Barber{

while(true){

wait(customer_arrived);

wait(mutex);

chairs_occupied --;

signal(mutex);

cut_hair( );

signal(barber_finished);

}

23

Another example

Motorbike assemblyOne process makes tyresAnother process makes chassis and

assembles motorbikeTyre processes and chassis process

should exit when a motorbike is complete

Barrier

24

Motorbike assemblyMakeTyres

/* signal when tyre is ready */

/* wait until tyre is assembled in a motorbike */

MakeChassis&Assemble

/*make chassis */

/*wait for both tyres to arrive*/

/*assemble motorbike*/

/*tell both tyres that they have been used*/

25

What happens here?

MakeTyreFunction( ){

signal(tyre);

wait(motorbike_done);

}

MakeChassis&Assemble( ){

/*make chassis *//*make chassis */

wait(tyre);

wait(tyre);

/* assemble motorbike*//* assemble motorbike*/

signal(motorbike_done);

signal(motorbike_done);

}

semaphore tyre = 0;

semaphore motorbike_done = 0;

26

This solution is incorrect

MakeTyreFunction( ){

signal(tyre);

wait(motorbike_done);

}

MakeChassis&Assemble( ){

wait(tyre);

wait(tyre);

/*make chassis and /*make chassis and assemble motorbike*/assemble motorbike*/

signal(motorbike_done);

signal(motorbike_done);

}

semaphore tyre = 0;

semaphore motorbike_done = 0;

27

Another possible solution (incomplete) ...

MakeTyreFunction( ){

wait(mutex);

count++;

if (count = = 2){

signal(assemble);

signal(tyre_exit);

signal(tyre_exit);

count = 0;}

signal(mutex);

wait(tyre_exit);

}

MakeChassis&Assemble( ){

wait(assemble);

/*make chassis and /*make chassis and assemble motorbike*/assemble motorbike*/

}

semaphore tyre_exit = 0; semaphore chassis_arrived = 0;

semaphore assemble = 0;

28

Another possible solution (complete)

MakeTyreFunction( ){

wait(chassis_arrived);

wait(mutex);

count++;

if (count = = 2){

signal(assemble);

signal(tyre_exit);

signal(tyre_exit);

count = 0;}

signal(mutex);

wait(tyre_exit);

}

MakeChassis&Assemble( ){

signal(chassis_arrived);

signal(chassis_arrived);

wait(assemble);

/*make chassis and /*make chassis and assemble motorbike*/assemble motorbike*/

}

semaphore tyre_exit = 0; semaphore chassis_arrived = 0;

semaphore assemble = 0;

29

Semaphore Essentially shared global variables. No control or guarantee of proper

usage.

Solution Use a higher level primitive called

monitors.

30

MonitorsHigher level synchronization primitive.Similar to a C++ class that ties data,

operations together.Processes may call the procedures in a

monitor whenever they want to, but cannot access the private data structures from functions outside the monitor.

31

Monitors

Unlike classes: Monitors ensure mutual exclusion

• Only one thread may execute a given monitor method at a time.

Monitors require all data to be private.

32

Monitors

33

Schematic View of a Monitor

34

MonitorsOnly one process can be active in a monitor at

any instant.Monitors are programming level constructs, so

compiler knows they are special and can handle calls to monitor procedures differently.

Compiler implements the mutual exclusion on monitor.

Programmer does not have to be aware of how the compiler arranges for mutual exclusion.

35

MonitorsTurn critical regions into monitor

procedures, no two processes shall execute their critical regions at same time.

36

MonitorsThe Java synchronized construct

implements a limited form of monitor

It is simple to turn a Java class into a monitor Make all data private Make all methods synchronized

37

class Queue{private ...; // queue data

}public void synchronized Add( Object item ) {

put item on queue;}public Object synchronized Remove() {

if queue not empty {remove item;return item;}

}

38

How can we change remove() to wait until something is on the queue?

Logically, we want to go to sleep inside of the monitor.

But if we hold on to the lock and sleep, then other threads cannot access the shared queue, add an item to it, and wake up the sleeping thread.

The thread could sleep forever.

39

Solution: Use condition variablesCondition variables enable a thread to

sleep inside a critical section.Any lock held by the thread is atomically

released when the thread is put to sleep.

40

Condition variable: is a queue of threads waiting for something inside a critical section.

Condition variables support three operations:

1. Wait(): atomic (release lock, go to sleep), when the process wakes up it re-acquires lock.

2. Signal(): wake up waiting thread, if one exists. Otherwise, it does nothing.

3. Broadcast(): wake up all waiting threadsRule: thread must hold the lock when doing

condition variable operations.

41

Monitor With Condition Variables

42

In Java: The wait() method causes a thread to

release the lock it is holding on an object; allowing another thread to run

wait() can only be invoked from within synchronized code

Use notify() to signal that the condition a thread is waiting on is satisfied.

Use notifyAll() to wake up all waiting threads.

notify() and notifyAll() can only be used within synchronized code

43

In Javaclass Queue {

private ...; // queue data}public void synchronized Add( Object item ) {

put item on queue;notify ();

}public Object synchronized Remove() {

while queue is emptywait (); // give up lock and go to sleep

remove and return item;}

44

MonitorsCondition variables are not countersThey do not accumulate signals like

semaphores doCondition variable is signaled with no

process waiting, signal is lost.

45

Monitors

How is this different from sleep and wakeup we saw earlier?

46

Monitors

47

Monitor Operations

Encapsulates shared data you want to protect.

Acquires mutex at the start.Operations on shared data.Temporarily releases mutex if it can’t

complete.Re-acquires mutex when it can continue.Releases mutex at the end.

48

Mesa-style: (Java, and most real operating systems)

The thread that signals keeps the lock (and thus the processor).

The waiting thread waits for the lock.

Hoare-style: (most textbooks)The thread that signals gives up the lock and

the waiting thread gets the lock.When the thread that was waiting and is now

executing exits or waits again, it releases the lock back to the signaling thread.