You are on page 1of 36

Process Synchronization 1

Process Synchronization

 N process solution
 Synchronization Hardware
 Semaphores
 Classic Problems of
Synchronization
 Monitors
 Synchronization Examples
 Atomic Transactions
N-Process Solution: Bakery Algorithm
 “Take a number for better service...”
 Before entering the CS, each Pi takes a number.
 Holder of smallest number enters CS next
 ..but more than one process can get the same number

 If Pi and Pj receive same number:


 lowest numbered process is served first
 Process resets its number to 0 in the exit section
 Notation:
 (a,b) < (c,d) if a < c or if a = c and b < d
 max(a0,...ak) is a number b such that:
b >= ai for i=0,..k
Bakery Algorithm

 Shared data:

 choosing: array[0..n-1] of boolean;

initialized to false

 number: array[0..n-1] of integer;

initialized to 0
Bakery Algorithm
Process Pi:
repeat
choosing[i]:=true;
number[i]:=max(number[0]..number[n-1])+1;
choosing[i]:=false;
for j:=0 to n-1 do {
while (choosing[j]);
while (number[j]!=0
and (number[j],j)<(number[i],i));
}
CS
number[i]:=0;
RS
forever
Bakery Algorithm: Proof
 Mutual Exclusion:
 If
Pi is in CS and Pk has already chosen its
number, then (number[i],i) < (number[k],k)
If they both had their numbers before the
decision, this must be true or Pi would not
have been chosen
If Pi entered its CS before Pk got its
number, Pk got a bigger number
So Pk cannot enter its CS until Pi exits.
 Progress, Bounded Waiting:
 Processes enter CS in FCFS order
Drawbacks of Software Solutions
 Complicated to program
 Busy waiting (wasted CPU cycles)
 It would be more efficient to block processes
that are waiting (just as if they had requested
I/O).
 This
suggests implementing the
permission/waiting function in the
Operating System
 But first, let’s look at some hardware
approaches.
Hardware Solution 1: Disable Interrupts
Process Pi:
repeat
disable interrupts
critical section
enable interrupts
remainder section
forever
 On a uniprocessor, mutual exclusion is preserved: while
in CS, nothing else can run
 because preemption impossible
 On a multiprocessor: mutual exclusion is not achieved
 Interrupts are “per-CPU”
 Generally not a practical solution for user programs
 But could be used inside an OS
Hardware Solution 2: Special Machine
Instructions

 Normally, the memory system restricts access to any


particular memory word to one CPU at a time
 Useful extension:
 machine instructions that perform 2 actions atomically on
the same memory location (ex: testing and writing)
 The execution of such an instruction is mutually
exclusive on that location (even with multiple CPUs)
 These instructions can be used to provide mutual
exclusion
 but need more complex algorithms for satisfying the
requirements of progress and bounded waiting
Synchronization Hardware
 Many systems provide hardware support for
critical section code
 Uniprocessors – could disable interrupts
 Currently running code would execute
without preemption
 Generally too inefficient on multiprocessor
systems
Operating systems using this not broadly
scalable
Synchronization Hardware

 Modern machines provide special atomic


hardware instructions
Atomic = non-interruptable
 Either test memory word and set value
 Or swap contents of two memory words
TestAndndSet Instruction

 Definition:

boolean TestAndSet (boolean *target)


{
boolean rv = *target;
*target = TRUE;
return rv:
}
Solution using TestAndSet
 Shared boolean variable lock., initialized to false.
 Solution:
do {
while ( TestAndSet (&lock )); /* do nothing
// critical section
lock = FALSE;

// remainder section

} while ( TRUE);
The Test-and-Set Instruction
 An algorithm that uses testset
 Test-and-Set expressed
for Mutual Exclusion:
in “C”:
 Shared variable lock is
int testset(int &i) initialized to 0
{  Only the first Pi who sets lock
int rv; enters CS
rv = *i;
*i = 1;
return rv;
Process Pi:
}
repeat
Non Interruptible (atomic)! while(testset(&lock));
One instruction reads then CS
writes the same memory lock:=0;
location RS
forever
Test-and-Set Instruction
 Mutual exclusion is assured: if Pi enters CS, the other Pj
are busy waiting
 Satisfies progress requirement
 When Pi exits CS, the selection of the next Pj to enter CS
is arbitrary: no bounded waiting (it’s a race!).
 Starvation is possible.
 Some processors (ex: Pentium) provide an atomic
Swap(a,b) instruction that swaps the content of a and b.
 (Same drawbacks as Test-and-Set)
Swap Instruction

 Definition:

void Swap (boolean *a, boolean *b)


{
boolean temp = *a;
*a = *b;
*b = temp:
}
Solution using Swap
 Shared Boolean variable lock initialized to
FALSE; Each process has a local Boolean
variable key.
 Solution:
do { key = TRUE;
while ( key == TRUE)
Swap (&lock, &key );
// critical section
lock = FALSE;
// remainder section

} while ( TRUE);
Using Swap for Mutual Exclusion
 Shared variable lock is
initialized to 0 Process Pi:
repeat
 Each Pi has a local key:=1
variable key repeat
 The only Pi that can swap(lock,key)
enter CS is the one until key=0;
which finds lock=0 CS
lock:=0;
 This Pi excludes all other
RS
Pj by setting lock to 1
forever
 (Same effect as test-
and-set)
Operating Systems or Programming
Language Support for Concurrency
 Solutions based on machine instructions such as
test and set involve tricky coding.

 We can build better solutions by providing


synchronization mechanisms in the Operating
System or Programming Language.
 (This leaves the really tricky code to systems
programmers)
Semaphores
 A Semaphore S is an integer variable that, apart from
initialization, can only be accessed through 2 atomic
and mutually exclusive operations:

 wait(S)
sometimes called P()
– Dutch proberen: “to test”

 signal(S)
sometimes called V()
– Dutch verhogen: “to increment”
Semaphore
 Synchronization tool that
does not require busy wait (S) {
waiting while S <= 0 ; // no-op
 Semaphore S – integer S--;
variable }
 Two standard operations
modify S: wait() and signal (S) {
signal() S++;
 Originally called P() }
and V()
 Less complicated
 Can only be accessed via
two indivisible (atomic)
operations
Semaphore as General Synchronization Tool
 Counting semaphore – integer
value can range over an Semaphore S;
unrestricted domain //initialized to 1
 Binary semaphore – integer wait (S);
value can range only between 0 Critical Section
and 1; can be simpler to signal (S);
implement
 Also known as mutex locks
 Can implement a counting
semaphore S as a binary
semaphore
 Provides mutual exclusion
Semaphore Implementation
 Must guarantee that no two processes can execute
wait () and signal () on the same semaphore at the
same time
 Thus, implementation becomes the critical section
problem where the wait and signal code are placed
in the critical section.
 Could now have busy waiting in critical section
implementation
But implementation code is short
Little busy waiting if critical section rarely occupied
 Note that applications may spend lots of time in
critical sections and therefore this is not a good
solution.
Semaphore Implementation with no Busy waiting
 With each semaphore there is an associated waiting
queue. Each entry in a waiting queue has two data
items:
 value (of type integer)
 pointer to next record in the list

 Two operations:
 block – place the process invoking the operation
on the appropriate waiting queue.
 wakeup – remove one of processes in the waiting
queue and place it in the ready queue.
Semaphore Implementation with no Busy waiting (Cont.)
 Implementation of wait:
wait (S){
value--;
if (value < 0) {
// add this process to waiting queue
block(); }
}
 Implementation of signal:
Signal (S){
value++;
if (value <= 0) {
// remove a process P from the waiting queue
wakeup(P); }
}
Busy Waiting Semaphores
 The simplest way to
implement
semaphores. wait(S):
while S<=0 do ;
 Useful when critical S--;
sections last for a
short time, or we have
lots of CPUs.
 S initialized to positive signal(S):
S++;
value (to allow
someone in at the
beginning).
Busy-Waiting Semaphores:
Observations
 When S>0:
 the number of processes that can execute wait(S)
without being blocked = S
 When S=0: one or more processes are waiting on S
 Semaphore is never negative
 When S becomes >0, the first process that tests S
enters enters its CS
 random selection (a race)
 fails Bounded Waiting condition
Atomicity in Semaphores
 The test-and-decrement
sequence in wait must be
atomic, but not the loop.
wait(S):
 Signal is atomic.
 No two processes can be T
allowed to execute atomic
sections simultaneously. S <= 0

 This can be implemented atomic F


by other mechanisms (in S--
the OS)
 test-and-set, or
 disable interrupts.
Using semaphores for solving critical
section problems
 For n processes
 Initialize semaphore Process Pi:
“mutex” to 1 repeat
 Then only one process is wait(mutex);
allowed into CS (mutual CS
exclusion) signal(mutex);
 To allow k processes
RS
into CS at a time, simply forever
initialize mutex to k
Semaphores in Action

Initialize mutex to 1

Process Pi: Process Pj:


repeat repeat
wait(mutex); wait(mutex);
CS CS
signal(mutex); signal(mutex);
RS RS
forever forever
Synchronizing Processes using
Semaphores
 Two processes:
 Define a semaphore
 P1 and P2
“synch”
 Statement S1 in P1 needs  Initialize synch to 0
to be performed before
statement S2 in P2
 Put this in P2:
 We want a way to make
P2 wait wait(synch);

 until P1 tells it is OK to S2;


proceed
 And this in in P1:
S1;
signal(synch);
Deadlock and Starvation
 Deadlock – two or more processes are waiting
indefinitely for an event that can be caused by only
one of the waiting processes
 Let S and Q be two semaphores initialized to 1
P0 P1
wait (S); wait (Q);
wait (Q); wait (S);
. .
. .
. .
signal (S); signal (Q);
signal (Q); signal (S);

 Starvation – indefinite blocking. A process may


never be removed from the semaphore queue in
which it is suspended.
Classical Problems of Synchronization
 Bounded-Buffer Problem
Bounded-Buffer Problem

 N buffers, each can hold one item


 Semaphore mutex initialized to the value 1
 Semaphore full initialized to the value 0
 Semaphore empty initialized to the value N.
Bounded Buffer Problem (Cont.)
 The structure of the producer process
do {
// produce an item

wait (empty);
wait (mutex);

// add the item to the buffer

signal (mutex);
signal (full);
} while (true);
Bounded Buffer Problem (Cont.)
 The structure of the consumer process
do {
wait (full);
wait (mutex);

// remove an item from buffer


signal (mutex);
signal (empty);

// consume the removed item

} while (true);

You might also like