Process/Thread
Synchronization (Part 2)
Modified from Chapter 6
for 170 with Nachos
threads, Tao Yang, 2012
Operating System Concepts – 8th Edition
Silberschatz, Galvin and Gagne ©2009
What to learn?
Software and hardware solutions
of the synchronization primitives
Deadlock/starvation
More synchronization applications
6.2
Implementation of Synchronization
Primitives
Software solutions through shared memory data
checking or message passing.
Assume that the LOAD and STORE instructions
are atomic for shared variables;
that is, cannot be interrupted
Hardware-assisted solutions
Properties (e.g. for implementing a lock)
Mutual exclusion: only one gets a lock.
Progress: when multiple threads try to acquire a
lock, one can get it if nobody has it.
Bounded waiting: lock waiting time is limited.
6.3
Software Solution for 2
processes/threads
Two processes use a shared variable to coordinate
int turn=0; // whose turn for the critical section
Process 0
while (turn != 0);
critical section
turn= 1; //give turn to P1
Process 1:
while (turn != 1);
critical section
turn= 0; //give turn to P0
Mutual exclusion? Progress? Bounded waiting?
6.4
Mutual exclusion?
Prove by contraction. Assume both Processes 0
and 1 are in the critical section.
Process 0
while (turn != 0);
turn==0
critical section
turn= 1; //give turn to P1
Process 1:
while (turn != 1);
turn==1
critical section
turn= 0; //give turn to P0
(turn==0) and (turn==1) is false
6.5
Progress?
The two processes use a shared variable to coordinate
int turn=0; // whose turn for the critical section
Process 0
while (turn != 0);
critical section
turn= 1;
Process 0 tries again:
Loop forever
while (turn != 0);
critical section
turn= 1;
6.6
Peterson’s Solution
Two process software solution (Text book chapter
6.3)
Assume that the LOAD and STORE instructions
are atomic; that is, cannot be interrupted.
The two processes share two variables:
int turn;
indicates whose turn it is to enter the critical
section.
Boolean ready[2]
indicate if a process is ready to enter the
critical section. ready[0] = true implies that
process P0 is ready!
6.7
Peterson’s Algorithm
Process P0:
ready[0] = TRUE;
Ready to enter critical section;
Wait if another process is in.
turn = 1;
while (ready[1] && turn == 1);
Critical section
Exit critical section
ready[0] = FALSE;
Process P1:
ready[1] = TRUE;
turn = 0;
while (ready[0] && turn == 0);
Critical section
ready[1] = FALSE;
6.8
Mutual exclusion?
Progress?
Bounded waiting?
Mutual Execution? Prove by contradition
Process P0:
ready[0] = TRUE;
turn = 1;
while (ready[1] && turn == 1);
critical section
ready[0]=T and (Ready[1]=F or turn=0)
ready[0] = FALSE;
Process P1:
ready[1] = TRUE;
turn = 0;
while (ready[0] && turn == 0);
critical section
ready[1]=T and (Ready[0]=F or turn=1)
ready[1] = FALSE;
Both conditions are true, which is not
possible6.9
Progress? Can both P0/P1 wait forever?
Process P0:
ready[0] = TRUE;
Loop forever
turn = 1;
while (ready[1] && turn == 1);
(Ready[1]=T and turn=1)
critical section
ready[0] = FALSE;
Process P1:
ready[1] = TRUE;
Loop forever
turn = 0;
while (ready[0] && turn == 0);
(Ready[0]=T and turn=0)
critical section
ready[1] = FALSE;
Both conditions are true, which is not
6.10
possible
Progress? Can P0 wait forever after P1 leaves
Process P0:
ready[0] = TRUE;
turn = 1;
while (ready[1] && turn == 1);
Loop forever
(ready[1]=T and turn=1)
critical section
ready[0] = FALSE;
Process P1:
ready[1] = TRUE;
turn = 0;
while (ready[0] && turn == 0);
critical section
ready[1] = FALSE;
ready[1]=F
Both conditions are true, which is not
possible. 6.11
Hardware Solution for Synchronization
Many systems provide hardware support for critical section
code
Uniprocessors – could disable interrupts
Currently running code would execute without preemption
Project 1.
Generally too inefficient on multiprocessor systems
Operating systems using this not broadly scalable
Modern machines provide special atomic hardware instructions
Atomic
= non-interruptable
Either test memory word and set value
Or swap contents of two memory words
6.12
Atomic TestAndSet Instruction
Definition: Fetch the value of a shared variable
and then set it to TRUE atomically.
boolean TestAndSet (boolean *target)
{
boolean rv = *target;
*target = TRUE;
return rv:
}
6.13
Lock Solution using TestAndSet
Shared boolean variable: lock.
“True” means somebody has acquired the lock.
initialized to FALSE.
Solution:
while ( TestAndSet (&lock )) ; // wait
Critical section;
lock = FALSE;
Mutual exclusion?
Progress?
Bounded waiting? no
6.14
Mutual exclusion? Assume P0 gets first,
and then P1
Process P0:
Property:
Lock=T somebody is in the critical section
Lock=F nobody is in the critical section.
while(TestAndSet (&lock));
critical section
lock = FALSE;
}
C1: lock was F in last TestAndSet().
TestAndSet() returns F
Now lock is T.
Process P1:
while(TestAndSet (&lock));
critical section
lock = FALSE;
C2: lock was F in last TestAndSet().
TestAndSet() returns F
Conditions C1 and then C2: cannot be true
6.15
Bounded Waiting?
Process P0:
Process P1:
TestAndSet (&lock)); //get in
…
TestAndSet(&lock);// wait
Lock=FALSE; //get out
TestAndSet(&lock);// get in
…
TestAndSet(&lock);// wait
Lock=FALSE; //get out
TestAndSet(&lock);// get in
…
TestAndSet(&lock);// wait
Lock=FALSE; //get out
TestAndSet(&lock);// get in
TestAndSet(&lock);// wait
6.16
Atomic Swap Instruction
Definition: exchange values of two
variables automatically.
void Swap (boolean *a, boolean *b)
{
boolean temp = *a;
*a = *b;
*b = temp:
}
6.17
Lock Solution using Swap
Shared Boolean variable lock initialized to FALSE; Each
process has a local Boolean variable key
Solution:
key = TRUE;
while ( key == TRUE)
Swap (&lock, &key );
Critical section
lock = FALSE;
Mutual exclusion, progress.
bounded waiting?
6.18
Key:
True
Lock:
False
TestAndSet Solution with Bounded Waiting
Enter Critical Section if:
Lock =False or Waiting[i]==False
Waiting[]
T
T
T
F
Assign with cyclic order for fairness
6.19
Bounded-waiting Mutual Exclusion
with TestAndSet()
waiting[i] = TRUE;
key = TRUE;
while (waiting[i] && key)
key = TestAndSet(&lock);
Loop if this process
should wait and
Lock =True
waiting[i] = FALSE;
Critical section
j = (i + 1) % n;
while ((j != i) && waiting[j]== False)
j = (j + 1) % n;
if (j == i) lock = FALSE;
else
waiting[j] = FALSE;
6.20
Find a waiting process j
and set waiting[j]=False
Or Set Lock=False
Deadlock and Starvation
Deadlock – two or more processes (or threads) are waiting
indefinitely for an event that can be only caused by one of these
waiting processes
Starvation – indefinite blocking. A process is in a waiting queue
forever.
Let S and Q be two locks:
P0
P1
Acquire(S);
Acquire(Q);
Acquire (Q);
Acquire (S);
.
.
.
.
.
.
Release (Q);
Release(S);
Release (S);
Release(Q);
6.21
Deadlock Avoidance
Order the locks and always acquire the locks in that order.
Eliminate circular waiting
P0
P1
Acquire(S);
Acquire(S);
Acquire(Q);
Acquire (Q);
.
.
.
.
.
.
Release(Q);
Release (Q);
Release(S);
Release (S);
6.22
Classical Problems of Synchronization
Bounded-Buffer Problem
Laundromat
Barriers
Readers and Writers Problem
6.23
Barriers
6.24
Barriers called multiple times
barrier(3);
barrier(3);
6.25
Implement a barrier
int count=0;
barrier(N) { //for N threads
mylock->Acquire();
count ++;
mylock->Release();
What’s wrong with this?
while (count <N)
Cond->Wait(mylock);
if(count==N) {
Cond->Broadcast(mylock);
Count=N for next
count=0;
barrier() called in
}
another thread
mylock->Release()
6.26
26
Readers-Writers Problem
A data set is shared among a number of concurrent processes.
Readers – only read the data set; they do not perform any
updates
Writers – can both read and write
Requirement:
allow multiple readers to read at the same time.
Only one writer can access the shared data at the same
time.
Reader/writer access permission table:
Reader
Writer
OK
NO
No
No
Reader
Writer
6.27
Readers-Writers (First try with 1 lock)
writer
do {
wrt.Acquire(); // wrt is a lock
//
writing is performed
wrt.Release();
} while (TRUE);
Reader
Reader
Writer
Reader
?
?
Writer
?
?
do {
wrt.Acquire(); // Use wrt lock
//
reading is performed
wrt.Release();
} while (TRUE);
6.28
2nd try using a lock + readcount
writer
do {
wrt.Acquire(); // Use wrt lock
//
writing is performed
wrt.Release();
} while (TRUE);
Reader
do {
readcount++; // add a reader counter.
if(readcount==1) wrt.Acquire();
//
reading is performed
readcount--;
if(readcount==0) wrt.Release();
} while (TRUE);
6.29
You may also use a binary semaphore
writer
do {
wrt.P(); // Use wrt semaphore with initial value=1
//
writing is performed
wrt.V();
What’s wrong with this?
} while (TRUE);
Reader
readcount is not protected
do {
readcount++; //initial value=0
if(readcount==1) wrt.P();
//
reading is performed
readcount--;
if(readcount==0) wrt.V();
} while (TRUE);
6.30
Readers-Writers Problem (Text Book)
Shared Data
Data
set
Semaphore
mutex initialized to 1
Semaphore
wrt initialized to 1
Integer
readcount initialized to 0
6.31
Readers-Writers Problem (textbook)
The structure of a writer process
do {
wrt.P() ; //Lock wrt
// writing is performed
wrt.V() ; //Unlock wrt
} while (TRUE);
6.32
Readers-Writers Problem (Cont.)
The structure of a reader process
do {
mutex.P() ;
readcount ++ ;
if (readcount == 1)
wrt.P() ;
mutex.V()
// reading is performed
mutex.P() ;
readcount - - ;
if (readcount == 0)
wrt.V() ;
mutex.V() ;
} while (TRUE);
6.33
© Copyright 2026 Paperzz