Professional Documents
Culture Documents
Module 3
● Process synchronization
● Race conditions – Critical section problem
● Peterson’s solution, Synchronization hardware
● Mutex Locks, Semaphores, Monitors
● Synchronization problems -Producer Consumer, Dining Philosophers and
Readers-Writers.
● Deadlocks
● Necessary conditions,
● Resource allocation graphs,
● Deadlock prevention,
● Deadlock avoidance – Banker’s algorithms,
● Deadlock detection, Recovery from deadlock.
Race Condition and
Critical Section Problem
Process Synchronization
● Processes executing concurrently in the OS may be
● independent process
● cooperating process
● Independent process
● They cannot affect or be affected by other processes executing in the
system.
● Cooperating process
● They can affect or be affected by other processes, executing in the
system.
● Share – resources, code, variable, memory etc
P1 P2 ● counter++ could be implemented as
{ {
---- ---- register1 = counter
register1 = register1 + 1
---- ----
counter = register1
counter++; ----
---- counter--; ● counter-- could be implemented as
---- ----
register2 = counter
---- ----
register2 = register2 - 1
} } counter = register2
Race Condition
Race condition is a situation where several process access and manipulate same data
concurrently and the outcome of execution depends on the particular order in which access
takes place .
● Why we need Process synchronization mechanisms?
● Concurrent access to shared data may result in data inconsistency
● Maintaining data consistency requires mechanisms to ensure the
orderly execution of cooperating processes – Process
synchronization mechanisms
Critical Section Problem
● The regions of a program that try to access shared resources and may
cause race conditions are called critical section.
● Portion of code Changing common variables, updating a table, writing a
file and so on
● To avoid race condition among the processes, we need to assure that
only one process at a time can execute within the critical section.
● The critical section problem is used to design a set of protocols
which can ensure that the Race condition among the processes will
never arise.
P1 P2
{ {
---- ----
---- ----
counter++; ----
---- counter--;
---- ----
---- ----
Critical Section
● When one process is in critical section, no other may be in its critical section
P1
{
----
----
counter++;
----
----
----
}
Solution to critical section problem must satisfy the following 3
requirements:
1. Mutual Exclusion
● If process Pi is executing in its critical section, then no other processes can be
executing in their critical sections
2. Progress
● If no process is executing in its critical section and there exist some processes that
wish to enter their critical section, then the selection of the processes that will
enter the critical section next cannot be postponed indefinitely
● Progress means that if one process doesn't need to execute into critical section
then it should not stop other processes to get into the critical section.
3. Bounded Waiting
- A bound must exist on the number of times that other processes are allowed to
enter their critical sections after a process has made a request to enter its critical
section and before that request is granted
Peterson’s Solution
Peterson’s Solution
● A classic software based solution to CSP
● Boolean flag[2]
4 The flag array is used to indicate if a process is ready to enter the critical
section.
4 flag[i] = true implies that process P is ready
i
Algorithm for Process Pi
do {
flag[i] = true;
turn = j;
while (flag[j] && turn = =
j);
critical section
flag[i] = false;
remainder section
} while (true);
Peterson’s Solution (Cont.)
Peterson’s Solution (Cont.)
wait( )
signal( )
wait(S)
{
while (S <= 0); // busy wait
S--;
}
signal(S)
{
S++;
}
S=1
Types of Semaphore
● Busy waiting
● While a process is in its CS, any other process that tries to enter its CS
must loop continuously in the entry code.
● Busy waiting wastes CPU cycles that some other process might be able to
use productively.
● Modification on wait()
● When a process executes the wait ( ) operation and finds that the semaphore
value is not positive, it must wait.
● However, rather than engaging in busy waiting, the process can block itself.
● The block() places a process into waiting queue associated with the semaphore,
and the state of the process is switched to the waiting state
● Then the control is transferred to CPU scheduler, which selects another process
to execute.
● Modification on signal()
● A process that is blocked, waiting on a semaphore S, should be restarted when
some other process executes a signal() operation.
● Wakeup() operation changes the process from the waiting state to the ready state.
Semaphore Implementation with no Busy
waiting
● Semaphore should be defined as follows:
typedef struct{
int value;
struct process
*list;
} semaphore;
wait(semaphore *S)
{
S->value--;
if (S->value < 0)
{
add this process to S- signal(semaphore *S) {
>list; S->value++;
block(); if (S->value <= 0) {
} remove a process P
} from
S->list;
wakeup(P);
}
Deadlock and Starvation
● The implementation of semaphore with a waiting queue may result in
Deadlock
● A situation where two or more processes are waiting indefinitely for an
event that can be caused by only one of the waiting processes
● Dining-Philosophers Problem
●Empty
● Counting semaphore, used to keep track of empty slots
● initial value is the number of slots in the buffer
●Full
● Counting semaphore, used to keep track of number of filled slots in buffer.
● initialized to the value 0
●Mutex
● Binary semaphore which is used to acquire and release lock
● initialized to the value 1
The structure of the producer process:
do {
...
/* produce an item */
...
wait(empty); //wait until empty >0 and then decrement empty
do {
wait(full); //wait until full>0 and then decrmnt full
wait(mutex); //acquire lock
...
/* remove an item from buffer */
...
signal(mutex); //release lock
signal(empty); //increment empty
...
/* consume the item */
...
} while (true);
Producer Consumer
do {
... do {
/* produce an item */ wait(full);
...
wait(empty); wait(mutex);
wait(mutex); ... /* remove an item
/* add produced item to from buffer */
the buffer */ ...
... signal(mutex);
signal(mutex); signal(empty);
signal(full); ...
} while (true); /*consume item*/
...
} while (true);
Dining-Philosophers Problem
● Five philosophers are sitting around a
circular table and their job is to think and
eat alternatively.
● Bowl of noodles/rice is placed in front
along with five chopsticks for each of the
philosophers.
● To eat, a philosopher needs both their
right and a left chopstick. A philosopher
can only eat if both immediate left and
right chopsticks of the philosopher is
available.
● In case if both immediate left and right
chopsticks of the philosopher are not
available then the philosopher puts down
their (either left or right) chopstick and
● Philosophers – processes starts thinking again.
● Chop stick – resources shared between processes
● Bowl – the data the processes want to access
Solution of Dining Philosopher Problem
● Use a semaphore to represent a chopstick
do {
wait (chopstick[i]);
wait (chopstick[ (i + 1) %
5] );
// eat
signal (chopstick[i] );
signal (chopstick[ (i + 1) %
5] );
// think
} while (TRUE);
Any Problem??
wait(S)
signal(S)
{
{
while (S <= 0);
S++;
S--;
}
}
Problem:
● Although this solution guarantees that no two neighbors are eating simultaneously,
it could still create a deadlock.
● Suppose that all five philosophers become hungry simultaneously and each grabs
their left chopstick. All the elements of chopstick will now be equal to 0.
● When each philosopher tries to grab his right chopstick, he will be delayed forever.
Possible remedies:
1. Allow at most four philosophers to be sitting simultaneously at the table. (count of
chopstick remains 5 itself)
2. Allow a philosopher to pick up his chopsticks only if both chopsticks are available.
(to do this, she must pick them up in a critical section)
● only read the data set; they do not perform any updates - Readers
do {
wait(rw_mutex);
...
/* writing is performed */
...
signal(rw_mutex);
} while (true);
R1
Database
Readcount =
R2
Mutex=1 rw_mutex=0
R3
do {
w4
wait(mutex);
read_count++;// number of readers has now increased by 1
if (read_count == 1)
wait(rw_mutex);//ensure no writer can enter if there
is even one reader
signal(mutex); //other readers can enter while this
current reader is inside the critical section.
/* reading is performed */
wait(mutex);
read count--; // a reader wants to leave
if (read_count == 0) // no reader is left in the critical section
signal(rw_mutex); //writers can enter
signal(mutex); //reader leaves
} while (true);
Assignment
● Synchronization hardware
● Mutex Locks
Monitors
● Syntax of monitor
monitor monitor-name
{
//shared variable
declarations
procedure P1 (…)
{ ….. }
…………..
procedure Pn (…)
{……}
Initialization code (…) { … }
❑A procedure defined within a monitor can access only those
parameters.
● This solution imposes the restriction that a philosopher may pick up his
chopsticks only if both of them are available.
● To code this solution, we need to distinguish among three states in which we may
find a philosopher. For this purpose, we introduce the following data structure
enum {thinking, hungry, eating} state [5];
● Philosopher I can set the variable state[i]=eating, only if his two neighbours are
not eating:
state[(i + 4) % 5] != EATING) && (state[(i + 1) % 5] != EATING)
● We also need to declare condition self[5]; where philosopher i can delay himself
when he is hungry but is unable to obtain the chopsticks he needs.
monitor DiningPhilosophers
{
enum { THINKING; HUNGRY, EATING) state [5] ;
condition self [5];
initialization_code()
{
for (int i = 0; i < 5; i++)
state[i] = THINKING;
}
}
● Each philosopher i invokes the operations pickup() and putdown() in
the following sequence:
DiningPhilosophers.pickup(i);
EAT
DiningPhilosophers.putdown(i);