Process synchronization
Frédéric Haziza <[email protected]>
Department of Computer Systems
Uppsala University
Spring 2008
Introduction Crit.Section Locks Semaphores Monitors
Shared Resource
RemarkSequential program use shared variablesConvenience for Global data structure
NecessityConcurrent program MUST use shared components
The only way to solve a problem: Communicate
The only way to communicate:One writes into something which the other one reads.
CommunicationReading and Writing shared variables
Sending and Receiving messages
2 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Synchronisation
Communication⇒ Synchronisation
SynchronisationMutual Exclusion
Condition synchronisation
Example (Mutual Exclusion)Whenever 2 processes need to take runs accessing shared objects
Example (Condition synchronisation)Whenever one process needs to wait for another
3 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
On the way to atomicityA Bank account example
Balance b with initially 100 sek..Person A wants to withdraw 70 sek, if possible.Person B wants to withdraw 50 sek, if possible.⇒ Balance should not be negative.
int b = 100; ⊲ initially 100 sek on the bank account
⊲ Person A tries to withdraw 70 sek
if (b − 70 > 0) {b = b − 70;
}
⊲ Person B tries to withdraw 50 sek
if (b − 50 > 0) {b = b − 50;
}
Can anything go wrong? b < 0 ??
4 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
AtomicityAnother bank account example
Balance b = 0 sek .Person A does a deposit of 100 sek.Person B does a deposit of 200 sek⇒ Balance should be 300 sek.
A Balance b B0 load R4, b
load R2, b 0add R2,#100store b, R2 100
add R4,#200200 store b, R4
Solution: Synchronisation (Locks,Semaphores,Monitors,Retry loops,...)
5 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
The programmer’s nightmare begins
The programmer must implement correct synchronization!
Example (lock S and Q)
P1 P2
lock(S) lock(Q)lock(Q) lock(S)
... ....unlock(Q) unlock(S)unlock(S) unlock(Q)
Leads to deadlock: Both P1 and P2 are waiting for each other
Additionally, bad implementation can lead to starvation.
6 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
AtomicityAnother example
sum:=0
print(sum)
while (sum < N)sum:=sum+1
while (sum < N)sum:=sum+1
while (sum < N)sum:=sum+1
while (sum < N)sum:=sum+1
What is printed?How many additions?
Anything betweenN and N+3
Anything betweenN and N*4
7 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Outline
1 Introduction
2 Critical Section Problem
3 Locks
4 Semaphores
5 Monitors
8 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Critical Section Problem
Critical Section Problem–LOCK (bank account)– ⊲ Wait for your turn, only one can update
if (can withdraw) {Do the withdrawal
}–UNLOCK (bank account)– ⊲ Release the lock
9 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Critical Section
CO [Process i = 1 to n] {while (true) {
LOCK (resource);Do critical section work;UNLOCK (resource);→֒ Do NON-critical section work; ←֓
}}
AssumptionA process that enters its CS will eventually exit⇒ A process may only terminate in its NON-critical section
10 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Say stop at entry section...
The main issue isHow do we make a thread wait?
A solution: Busy waitingCheck repeatedly a condition until it becomes true.
Another solution: BlockingWaiting threads are de-scheduled
High overhead
Allows processor to do other things
Hybrid methods: Busy-wait a while, then block
11 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Challenge
TaskDesign the LOCK and UNLOCK routines.
Ensuring:Mutual Exclusion
No deadlocks
No unnecessary delays
Eventual Entry
12 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Reformulation
Let in1 and in2 be boolean variables.
in1 is true if Process 1 is in its CS, false otherwise
in2 is true if Process 2 is in its CS, false otherwise
Avoid that both in1 and in2 are true
MUTEX: ¬(in1 ∧ in2)
A solution:wait_until(!in2) and then in1 = true; //ATOMICALLY!!<wait_until(!in2) and then in1 = true;>
13 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Coarse-grained solution
bool in1 = false, in2 = false;⊲ MUTEX: ¬(in1 ∧ in2)
⊲ Process 1
while (true) {< wait_until(!in2) and thenin1 = true; >Do critical section workin1=false;Do NON-critical section
}
⊲ Process 2
while (true) {< wait_until(!in1) and thenin2 = true; >Do critical section workin2=false;Do NON-critical section
}
But n processes⇒ n variables...
14 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Coarse-grained solution
Only 2 interesting states: locked and unlocked⇒ 1 variable is enough
bool lock = false;
while (true) { ⊲ Process 1
< wait_until(!lock) and thenlock = true; >Do critical section worklock=false;Do NON-critical section
}
while (true) { ⊲ Process 2
< wait_until(!lock) and thenlock = true; >Do critical section worklock=false;Do NON-critical section
}
15 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Outline
1 Introduction
2 Critical Section Problem
3 Locks
4 Semaphores
5 Monitors
16 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
How to?
< await(!lock) and then lock = true;>
Read-Modify-Write atomic primitivesTest and Set (TAS):Value at Mem[lock_addr] loaded in a specified register.
Constant “1” atomically stored into Mem[lock_addr]
Swap:Atomically swaps the value of REG with Mem[lock_addr]
Compare and Swap (CAS):Swaps if Mem[lock_addr]==REG2
Fetch and Add (FA):Increments a value by a given constant and returns the old value
17 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Test And Set
bool TAS(bool lock) {< bool initial = lock; ⊲ Save the initial value
lock = true; ⊲ Set lock
return initial; > ⊲ Return initial value
}
18 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Spin Lock
bool TAS(bool lock) {< bool initial = lock; ⊲ Save the initial value
lock = true; ⊲ Set lock
return initial; > ⊲ Return initial value
}
lock(lock_variable) {while(TAS(lock_variable)==true){};
⊲ Bang on the lock until free
}
unlock(lock_variable) {lock_variable:=false; ⊲ Reset to the initial value
}
19 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Test and Test and Set
lock(lock_variable) {while(TAS(lock_variable)==true){};
}
lock(lock_variable) { ⊲ More optimistic solution
while (true) {if(TAS(lock_variable)==false) break;⊲ Bang on the lock once
while(lock_variable==true){};}
}
20 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Tie Breaker – Petersson’s algorithm
Remember who had the lock latest!
bool in1 = false, in2 = false;int last = 1;
⊲ Process 1
while (true) {in1=true, last = 1;while(in2 and last==1){};Do critical section workin1=false;Do NON-critical section work
}
⊲ Process 2
while (true) {in2=true, last = 2;while(in1 and last==2){};Do critical section workin2=false;Do NON-critical section work
}
21 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Ticket-based lock
CO [Process i = 1 to n] {while (true) {
<turn[i] = number; number = number+1;>
< await(turn[i] == number);>
Do critical section< next = next+1;>
Do NON-critical section}
}
Fetch and Add (FA)
Increments a value by a given constant and returns the old value
CO [Process i = 1 to n] {while (true) {
turn[i] = FA(number,1);while(turn[i] != next){}; ⊲ Can even have a back-offDo critical sectionnext = next+1; ⊲ Is that safe?Do NON-critical section
}}
22 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
So locks... ?
Are busy-waiting protocols complex?No clear distinction between variables used:
• for synchronization• for computing results
Busy-waiting is often inefficient• Usually more processes/threads than processors• Processor executing a spinning process can be more
productively employed to execute another process
SemaphoresFirst synchronisation tool (and remains one of the most important).⇒ Easy to protect critical sections.⇒ Included in (almost) all parallel programming libraries.
23 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Outline
1 Introduction
2 Critical Section Problem
3 Locks
4 Semaphores
5 Monitors
24 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Semaphore
Shared variable with 2 atomic methods:
P(Semaphore s) {⊲ Probeer (try) / Passeren (pass) / Pakken (grab)
< wait until c > 0, then c := c-1; >
⊲ must be atomic once c > 0 is detected
}
V(Semaphore s) {⊲ Verhoog (increase)
< c = c + 1; > ⊲ must be atomic
}
Init(Semaphore s, Integer i){ c := i; }
25 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Semaphores, what for?
Critical section: Mutual exclusion
Barriers: Signaling events
Producers and Consumers
Bounded buffers: Resource counting
26 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Critical section
sem mutex; Init(sem,1);
10
while (true) { ⊲ Process 1
P(mutex);Critical sectionV(mutex);NON-Critical section
}
while (true) { ⊲ Process 2
P(mutex);Critical sectionV(mutex);NON-Critical section
}
27 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Barriers: Signaling events
sem arrive1, arrive2;Init(arrive1,0); Init(arrive2,0);
0 0
Section A Section B
Barrier
. . . ⊲ process 1 in section A
V(arrive1); ⊲ signal arrival
P(arrive2); ⊲ Wait for the other process
. . . ⊲ process 1 in section B
. . . ⊲ process 2 in section A
V(arrive2); ⊲ signal arrival
P(arrive1); ⊲ Wait for the other process
. . . ⊲ process 2 in section B
28 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Semaphores: Procuders and Consumers
Producer Consumer
Shared Resource
29 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Semaphores: Procuders and Consumers
Producer Consumer
put take
Buffer
Empty
1
Full
0
Split Binary SemaphoreBoth are binary semaphores
32 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Semaphores: Procuders and Consumers
typeT buf; ⊲ Buffer of some type T
sem empty, full;Init(empty,1); Init(full,0);
Empty
1
Full
0
while (true) { ⊲ Producer
. . .P(empty);buf = data;V(full);. . .
}
while (true) { ⊲ Consumer
. . .P(full);result = buf;V(empty);. . .
}
33 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
In the last example...
Single communication buffer
No waiting if data are produced and consumed at the samerate
But in general, producer/consumer execution is bursty
Exampleproducer produces several items in a quick succession
does more computation
produces another set of items
Solution: Increase the buffer capacity
34 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Bounded buffer: Resource counting
Producer Consumer
put take
Buffer
Emptyn
Full
0
35 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
The Buffer
. . .
frontrear
Put: buf[rear] = data; rear = (rear + 1) %n
Take: result = buf[front]; front = (front + 1) %n
36 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Bounded buffer: Resource counting
typeT buf[n]; ⊲ Array of some type T
int front=0, rear=0;sem empty, full;Init(empty,n); Init(full,0);
Emptyn
Full
0
sem mutexP, mutexT; Init(mutexP,1), Init(mutexT,1);
while (true) { ⊲ Producer
. . .P(empty);P(mutexP);buf[rear] = data;rear = (rear+1) %n;V(mutexP);V(full);. . .
}
while (true) { ⊲ Consumer
. . .P(full);P(mutexT);result = buf[front];front = (front+1) %n;V(mutexT);V(empty);. . .
}
37 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Semi-Conclusion
1
Critical Section
0 0
Blockingsemaphore
Barriers/Signaling
Empty
1
Full
0
Split Binarysemaphore
n
ResourceCounting
38 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Dining Philosophers Problem
Five philosophers sit around a circular table. Each philosopherspends his life alternately thinking and eating. In the center ofthe table is a large patter of spaghetti. Because the spaghetti islong and tangled – and the philosophers are not mechanicallyadept – a philosopher must use two forks to eat a helping.Unfortunately, the philosophers can afford only five forks. Onefork is placed between each pair of philosophers. And theyagree that each will use only the forks to the immediate left andright. The problem is to write a program to simulate thebehavior of the philosophers. The program must avoid theunfortunate (and eventually fatal) situation in which allphilosophers are hungry but non is able to acquire both forks –for example, each holds one fork and refuses to give it up.
39 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Dining Philosophers Problem
Philopher0
Philopher1
Philopher2
Philopher3
Philopher4
Spaghetti
while (true) { ⊲ Philosopherithink;acquire forks;eat;release forks;
}
sem fork[5] = {1,1,1,1,1}while (true) { ⊲ Philosopher0,1,2,3,4
think;P(fork[i]);P(fork[i+1]);eat;V(fork[i]);V(fork[i+1]);
}
40 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Dining Philosophers Problem
See lab 2
41 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Readers/Writers
Shared Resource
WriterReadersWriterWriter
Example of selective mutual exclusion
Example of general condition synchronization
42 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Readers/Writers as an Exclusion Problem
First Solution:1 Overconstrain the problem2 Relax the constraints
Let rw be a mutual exclusion semaphore⇒ Init(rw,1);
Readers 1,..,M
while (true) {. . .P(rw); ⊲ grab exclusive access lock
Read the databaseV(rw); ⊲ release the lock
. . .}
Writers 1,..,N
while (true) {. . .P(rw); ⊲ grab exclusive access lock
Write the databaseV(rw); ⊲ release the lock
. . .}
Readers – as a group – need to lock out writers
but only the first needs to grab the lock (i.e. P(rw))
Subsequent readers can directly access the database
43 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Relaxing constraints
int nr = 0; ⊲ number of active readers
sem rw; Init(rw,1); ⊲ lock for reader/writer exclusion
sem mutexR; Init(mutexR,1); ⊲ lock for reader access to nr
Readers 1,..,M
while (true) {. . .P(mutexR);
nr = nr + 1;if (nr == 1) P(rw); ⊲ if first, get lock
V(mutexR);Read the databaseP(mutexR);
nr = nr - 1;if (nr == 0) V(rw); ⊲ if last, release lock
V(mutexR);. . .
}
Writers 1,..,N
while (true) {. . .P(rw); ⊲ grab exclusive access lock
Write the databaseV(rw); ⊲ release the lock
. . .}
44 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Readers/Writers using Condition Synchronization
Second Solution:1 Count the number of each kind of processes trying to
access the database2 Constrain the values of the counters
Let nr and nw be nonnegative counters;
BAD: (nr > 0 ∧ nw > 0 ) ∨ nw > 1
Symmetrically, good states, RW = BADRW: (nr == 0 ∨ nw == 0 ) ∧ nw ≤ 1
45 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Coarse-grained solution using ConditionSynchronization
int nr = 0, nw = 0;⊲ RW: (nr == 0 ∨ nw == 0) ∧ nw ≤ 1
Readers 1,..,M
while (true) {. . .< await(nw == 0) nr = nr + 1; >
Read the database< nr = nr - 1; >
. . .}
Writers 1,..,N
while (true) {. . .< await(nr == 0 and nw == 0) nw = nw + 1; >
Write the database< nw = nw - 1; >
. . .}
46 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
So ... semaphores, really?
Common use in programming languages that do notintrinsically support other forms of synchronization.
They are the primitive synchronization mechanism in manyoperating systems.
The trend in programming language development, though, istowards more structured forms of synchronization, such asmonitors.
Inadequacies in dealing with (multi-resource) deadlocks
Do not protect the programmer from the easy mistakes oftaking a semaphore that is already held by the sameprocess, and forgetting to release a semaphore that hasbeen taken.
47 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Outline
1 Introduction
2 Critical Section Problem
3 Locks
4 Semaphores
5 Monitors
48 OSKomp’08 | Process synchronization
Introduction Crit.Section Locks Semaphores Monitors
Monitors
My old harddrive crashed, where the source code was.
I just have the PDF file in handout mode(go to slide 30)
49 OSKomp’08 | Process synchronization