Title: Process Synchronization
1Process Synchronization
2Background
- In a multi-programmed OS, processes/threads often
need to share resources printers, files, data in
memory, etc. - Concurrent access to shared resources may result
in inconsistent/improper operation. - OS must provide mechanisms to ensure orderly
execution of cooperating processes
3Example
- An application with two processes P1 and P2 that
share data. - shared float balance
- ----------------
- Process P1 balance balance amount1
- ---------------
- Process P2 balance balance - amount2
4Example-Cont.
Process P1
Process P2
- a1 LOAD R1, balance
- b1 MOV R2, amount1
- c1 ADD R1, R2
- d1 STORE R1, balance
a2 LOAD R1, balance b2 MOV R2,
amount2 c2 SUB R1, R2 d2 STORE R1, balance
- Assume initial values balance 100, amount1
20 and amount2 50. - What is the expected balance after P1 and P2 are
executed? - What if the processor executes the following
sequence - a1, b1, a2, b2, c2, d2, c1, d1
5Critical Section Problem
6Example--Cont.
- In the previous example
- In P1, the statement
- balance balance amount1
- is a critical section
- In P2, the statement
- balance balance - amount2
- is a critical section
7Solution to Critical Section Problem
- 1. Mutual Exclusion at most one process is in
its critical section at any time. - 2. Progress If no process is executing its
critical section, a process that wishes to enter
can get in. Only those processes that are not in
the remainder section can participate in the
decision to determine which process enters its
critical section next. - 3. Bounded Waiting No process is postponed
indefinitely. There must be a bound on the
number of times that other process are allowed to
get in after a process has made a request to get
in.
8Initial Attempt
- Two processes P0 and P1
- The general structure for each process Pi
- repeat
- Entry section
- critical section
- exit section
- remainder section
- until false
-
9Disabling Interrupts to Implement the Critical
Section
Process P1
Process P0
- repeat
- disableInterrupts()
- Critical Section
- enableInterrupts()
- remainder Section
- until flase
repeat disableInterrupts() Critical
Section enableInterrupts() remainder
Section until flase
10Disabling Interrupts to Implement the Critical
Section
shared float balance
Process P1
Process P0
- float amt0
- ....
- disableInterrupts()
- balance balance amt0
- enableInterrupts()
float amt1 ... disableInterrupts()
balance balance - amt1 enableInterrupts()
11Algorithm 0
Shared boolean lock FALSE shared float
balance
Process P0
Process P1
- float amt0
-
- while (lock TRUE)
-
- lock TRUE
- balance balance amt0
- lock FALSE
float amt1 . while (lock TRUE) lock
TRUE balance balance amt1 lock FALSE
12Algorithm 1
- shared boolean turn 0 // turn is either 0 or 1
Process P0
Process P1
Repeat while (turn 1) Critical
Section turn 1 Remainder Section until
flase
Repeat while (turn 0) Critical
Section turn 0 Remainder Section until
flase
13Algorithm 1
- shared boolean turn 0 // turn is either 0or 1
Process Pi
repeat while (turn j) Critical
Section turn j Remainder Section until
flase
- Satisfies mutual exclusion
- does not satisfy the progress requirement the
two processes must alternate trough the Critical
section.
14Algorithm 2
- Shared boolean Flag0..1 false, false
Process Pi
repeat Flagi true while (Flagj
true) Critical Section Flagi
false Remainder Section until flase
- Flagi true gt process want to get into
critical section
15Algorithm 3
- Shared boolean Flag0..1 false, false
- boolean turn 0
Process Pi
repeat Flagi true turn j while
(Flagj and turnj) Critical Section
Flagi false Remainder Section until flase
- Turn i gt process i can enter its critical
section - Flagi true gt process want to get into
critical section - Solves the critical section problem for two
processes
16Mutual Exclusion with Test Set
- The test set instruction is a machine level
instruction that tests and sets a variable
atomically. The instruction can be defined as
follows - boolean test_and_set (boolean target)
- // sets target to True and returns its old
value - boolean OldValue
- OldValue target
- target True
- return OldValue
-
17Example
- boolean X False
- boolean temp
- temp test_and_set( X)
- What are the values of temp and X ?
- Temp False
- X True
18Mutual Exclusion with Test Set
- The main characteristic of the TestSet
instruction is that it is executed
atomically--I.e. as one un-interruptable
instruction. - Thus if two TestSet instructions are executed
simultaneously (each on a different CPU), they
will be executed sequentially in some arbitrary
order.
19How Test Set is used for Mutual Exclusion
- shared boolean lock False
-
while ( TestSet(lock) True )
NULL // spin lock lt Critical Sectiongt lock
FALSE // atomic ltremainder sectiongt
- Satisfies Mutual Exclusion condition
- Does not satisfy bounded waiting condition
- While a process is in its critical section , all
other processes which want to execute their
critical sections continuously execute the while
loop gt waist of computing power.
20Semaphores
- A semaphore is a synchronization mechanism that
does not require busy waiting. - A semaphore is an integer that can only be
accessed through one of two atomic operations
wait() and signal().
Wait(S) while (Slt 0) NULL S S -1
Signal(S) S S 1
21Example Critical Section for n Processes
- shared semaphore Mutex1
-
-
- wait(Mutex)
- ltcritical sectiongt
- signal(Mutex)
- ltremainder sectiongt
- Does not satisfy bounded waiting condition
- Still has busy waiting
22Semaphores as General Synchronization Tools
23Blocking/Active Semaphore
- class semaphore
-
- private
- int value
- L is a list of process Ids // L may be
organized as a FIFO list - public
- initialize( InitialValue)
-
- value InitialValue
- L is an empty list
-
- // CONTINUE ON NEXT SLIDE
24Blocking/Active Semaphore (Cont.)
- wait( )
-
- value value -1
- if ( value lt 0)
-
- add the PID of this process to L
- // L may be organized as a FIFO queue
- block this process
-
-
- // CONTINUE ON NEXT SLIDE
-
25Blocking/Active Semaphore (Cont.)
- signal ( )
-
- value value 1
- if (value lt 0)
-
- remove a process P from L // may be done on a
- // FCFS basis
- wakeup(P)
-
-
- // end of class semaphore
26Producer-Consumer Problem
- A Producer process/thread produces data items
that are consumed by another process/thread (the
Consumer). - Each item produced by the producer needs to be
consumed by the consumer. - Shared memory is used to have the producer pass
data items to consumer
27Producer-Consumer Problem
- Assume threads use one shared variable X
- Shared itemType X
-
-
producer() Repeat . Compute next
item NextP . X NextP
until false
consumer() Repeat . NextC X
// Consume . Use NextC ...
until false
28Producer-Consumer Problem
- Assume threads use one shared variable X
- Shared itemType X
- Shared semaphore P 0
-
-
producer() Repeat . Compute next
item NextP . X NextP
signal(P) until false
consumer() Repeat . wait(P)
NextC X // Consume . Use NextC
... until false
29Producer-Consumer Problem
- Assume threads use one shared variable X
- Shared itemType X
- Shared semaphore P 0, C 1
-
-
producer() Repeat . Compute next
item NextP . wait(C) X
NextP signal(P) until false
consumer() Repeat . wait(P)
NextC X // Consume signal(C) .
Use NextC ... until false
30Producer-Consumer Problem
- Assume threads use a buffer of size N
- Shared itemType buffN
-
-
-
producer() int in 0 Repeat .
Compute next item NextP . Buffin
NextP in (in1) N
until false
consumer() int out 0 Repeat .
NextC buffout // Consume out (out1)
N . Use NextC ...
until false
31Producer-Consumer Problem
- Previous solution does not prevent consumer from
consuming from empty buffer - Does not prevent producer from inserting a new
item into a full buffer.
32Producer-Consumer Problem
- Assume threads use a buffer of size N
- Shared itemType buffN int counter0
-
-
-
producer() int in 0 Repeat .
Compute next item NextP . while
(counter gtN) NULL Buffin NextP
in (in1) N counter until
false
consumer() int out 0 Repeat .
while (counter lt0) NULL NextC
buffout // Consume out (out1) N
--counter . Use NextC ...
until false
33Producer-Consumer Problem
- Critic of Previous Solution
- race condition may occur on access to shared
variable counter - If one producer one consumer, access to shared
buff does not cause any race conditions (why ?) - If multiple producers consumers, access to
shared buff may cause race condition.
341 Producer 1 Consumer
- Shared semaphore full_slots0, empty_slotsN
- Shared itemType buffN
producer() int in 0 Repeat .
Compute next item NextP .
wait(empty_slots) Buffin NextP
in (in1) N signal(full_slots)
until false
consumer() int out 0 Repeat .
wait(full_slots) NextC buffout //
Consume out (out1) N
signal(empty_slots) . Use NextC
... until false
35Multiple Producers Consumers
- Shared semaphore full_slots0, empty_slotsN,
- Cmutex, Pmutex1
- Shared itemType buffN
producer() int in 0 Repeat .
Compute next item NextP .
wait(empty_slots) wait(Pmutex)
Buffin NextP in (in1) N
signal(Pmutex) signal(full_slots)
until false
consumer() int out 0 Repeat .
wait(full_slots) wait(Cmutex) NextC
buffout // Consume out (out1) N
signal(Cmutex) signal(empty_slots)
. Use NextC ... until false
36Reader-Writer Problem
- Suppose a resource is to be shared among a
community of processes of two types readers
writers. - A reader process can share the resource with any
number of other readers but not with a writer - A writer must have exclusive access to the
resource
37Readers First Solution
- Algorithm ideas
- no reader should wait unless a writer is using
the resource - as long as a reader is using the resource, a
writer who wishes to use the resource must wait - 1st reader must check to make sure no writer is
using the resource - all subsequent readers do not have to wait
provided at least one process is reading
38Readers First Solution Cont.
- Shared semaphore WriterBlock 1, Mutex1
- shared int readersCount 0
- Writer( )
-
- while (true)
- ltother stuffgt
- wait(WriterBlock)
- ltwriting is performedgt
- signal(WriterBlock)
- .
-
39Readers First Solution cont.
- reader( )
- while (true)
- ltother stuffgt
- wait(Mutex)
- readersCount
- if (readersCount 1) wait(WriterBlock)
- signal(Mutex)
- ltreading is performedgt
- wait(Mutex)
- readersCount--
- if (readersCount 0) signal(WriterBlock)
- signal(Mutex)
40Dining-Philosophers Problem
- Five philosophers sitting at a table. Each has
bowl of rice in front of him/her. - There are five chopsticks, two at left and right
of each philosopher, as shown above. - A philosophers life consists of thinking and
eating. - A philosopher needs both left and right
chopsticks to be able to eat. - A chopstick can be used by only one philosopher
at a time.
41Dining-Philosophers Problem
- There are five philosopher processes numbered 0
through 4. Between each pair of philosophers is a
chopstick. The chopsticks are also numbered 0
through 4, so that CStick i is between
philosophers i and i-1 (all arithmetic on Cstick
numbers and philosopher numbers is modulo 5 so
CStick 0 is between philosophers 4 and 0, and
Cstick 1 is between philo. 0 and 1).
42Dining-Philosophers Problem
- Semaphore CStrick5 (all initialized to 1)
- Philosopher i
- while (true)
- THINK()
- wait(CSticki) // pick left chop stick
- wait(CStick(i1)5 // pick right chop stick
- EAT()
- signal(CSticki)
- signal(CStick(i1)5)
-
- Algorithm has the potential of deadlock
43Dining-Philosophers Problem
- Semaphore CStrick5 (all initialized to 1)
- Philosopher i
- while (true)
- THINK( )
- if (i2 0) // if even numbered
- wait(CSticki) // pick left chop stick
- wait(CStick(i1)5 // pick right chop stick
-
- else // if odd numbered
- wait(CStick(i1)5 // pick right chop stick
wait(CSticki) // pick left chop stick -
- EAT( )
- signal(CSticki)
- signal(CStick(i1)5)
-