Module 3.1
Module 3.1
2
Producer Process
The code of producer process is:
while (true)
{
P1: while (count == sizeofbuffer)
P2: ;
P3: buffer[in] = item;
P4: in = (in + 1) % sizeofbuffer;
P5: a = count;
P6: a = a + 1;
P7: count = a;
}
3
Consumer Process
The code of consumer process is:
while(true)
{
C1: while (count == 0)
C2: ;
C3: item = buffer[out];
C4: out = (out+1) % sizeofbuffer;
C5: b = count;
C6: b = b - 1;
C7: count = b;
}
4
Serial Execution
With serial execution, processes are executed one after another.
CPU is switched to another process only after completion of the currently running process.
Concurrent Execution (or) Parallel Execution
With concurrent execution, CPU can be transferred to another process during execution of the current
process.
We get correct output when the processes are executed either serially or concurrently.
We may get wrong output in some sequences of concurrent execution of the processes.
One example concurrent execution of instructions of producer & consumer processes that leads to wrong
result is P1, P2, P3, P4, P5, P6, C1, C2, C3, C4, C5, C6, P7, C7. 5
while (true) while(true)
{ {
P1: while (count == sizeofbuffer) C1: while (count == 0)
P2: ; C2: ;
P3: buffer[in] = item; C3: item = buffer[out];
P4: in = (in + 1) % sizeofbuffer; C4: out = (out+1) % sizeofbuffer;
P5: a = count; C5: b = count;
P6: a = a + 1; C6: b = b - 1;
P7: count = a; C7: count = b;
} }
6
If the position of buffer is
When the statements of producer and consumer are executed in the order P1, P2, P3, P4, P5, P6, C1, C2, C3,
C4, C5, C6, P7, C7 then the position of buffer is
When the statements of producer and consumer are executed in the order P1, P2, P3, P4, P5, P6, C1, C2,
C3, C4, C5, C6, C7, P7 then the position of buffer is
Ex: What would be the different values that A, B can possibly take after the execution of the processes P1,
P2 concurrently?
Initial values of A and B are 6 and 4 respectively.
9
Concurrent execution sequence1: I1, I2, I11, I12
A=6-4=2
B=4+2=6
A=2+1=3
B=6-1=5
A=3, B=5
a = count
a=a+1
count = a
This restriction on the execution of processes leads to generation of correct output in the concurrent
execution of processes.
Solutions for Critical Section Problem (or) Solutions for Implementing Mutual Exclusion
15
Any solution to the critical section problem must satisfy the following three conditions
1) Mutual exclusion
2) Progress
3) Bounded waiting
Mutual Exclusion
At a time, only one process should enter into its critical section.
Progress
All processes should not enter into deadlock state. At any time, at least one process should be in the
running state.
Bounded waiting
All processes should be given equal chance to enter into their critical sections.
16
Peterson’s Solution
o boolean flag[2];
turn=1 - indicates that the producer process can enter into its critical section.
turn=2 - indicates that the consumer process can enter into its critical section.
flag indicates whether a process is ready to enter into its critical section or not.
flag[1]=true - indicates that the producer process is ready to enter into its critical section.
flag[2]=true - indicates that the consumer process is ready to enter into its critical section.
17
Initially, flag[1] and flag[2] are set to false.
When the producer process wants to enter into its critical section then the producer process sets its
corresponding flag value to true.
If the consumer process is also ready to enter into its critical section then the producer process allows the
consumer process to enter into its critical section by setting the turn value to the consumer process.
Producer process waits until consumer process comes out from its critical section.
Producer process sets its flag value to false after coming out from its critical section.
Same procedure is followed by the consumer process when it wants to enter into its critical section.
18
19
Hardware Solution
When a process wants to enter into its critical section then it must acquire the ‘lock’. i.e. set ‘lock’ value
to true.
After coming out from the critical section, the process has to release the ‘lock’. i.e. set ‘lock’ value to
false.
do {
acquire lock
critical section
release lock
remainder section
} while (TRUE);
20
TestandSet()
‘TestandSet’ is a hardware instruction which performs operations on the ‘lock’ variable to solve the
critical section problem.
This function takes ‘lock’ variable as input and returns a boolean value.
22
23
Swap()
‘Swap’ is another hardware instruction used to solve the critical section problem. The definition of Swap()
instruction is
1) Binary semaphore
2) Counting semaphore
Binary semaphore is also called as mutex variable because binary semaphore is used to implement mutual
exclusion.
Initial value of counting semaphore is equal to the number of instances of the resource.
A queue is associated with each semaphore variable.
1) wait()
2) signal()
wait(s)
{
s=s-1;
if(s<0)
{
block the process;
Insert the process in the queue associated with the semaphore
variable s;
}
}
The definition of signal() operation is
signal(s)
{
s=s+1;
if(s<=0)
{
remove a process form the queue associated with the semaphore
variable s;
restart the removed process;
}
}
To solve the critical section problem, a process has to call wait() operation on the semaphore variable
before entering into its critical section and signal() operation after coming out from its critical section.
wait(S)
Critical Section
signal(S)
Solution to the critical section problem of producer-consumer is
Monitor
Procedure1(list of parameters)
{
------
}
Procedure2(list of parameters)
{
-----
}
-----
------
Initializationcode( )
{
----
}
}
In a monitor, zero or more shared variables are declared using syntax rules of java language.
Similarly, zero or more condition variables are declared with the following syntax
condition listofvariables;
Zero or more procedures are defined. Procedures do not return any value.
Shared variables are used to store values and can be accessed only by the procedures of monitor.
Procedures of the monitor can access and perform operations on the shared variables of the monitor.
Initialization code is like a constructor in a java class and is used for initializing the shared variables of the
monitor.
Condition variables are used to solve the critical section problem.
When any process calls wait() operation on any condition variable then the execution of that process will be
stopped and will be placed into the queue associated with that condition variable.
When any process calls signal() operation on any conditional variable then a waiting process from the queue
of the condition variable will be restarted.
At any time, only one process is allowed to call a procedure of the monitor.
When a process say P1 invokes a procedure of the monitor and the procedure is executing then at the same
time if any other process say P2 tries to call a procedure of the monitor then the process P2 has to wait.
With the above property of monitor, mutual exclusion is implemented automatically in the monitor.
Monitor solution for critical section problem of Producer – Consumer
Monitor PC
{
int sizeofbuffer, Buffer[], in, out, count, item;
condition full, empty;
insert(int x)
{
if(count==sizeofbuffer)
wait(full);
Buffer[in]=x;
in=(in+1)%sizeofbuffer;
count=count+1;
signal(empty);
}
delete()
{
if(count==0)
wait(empty);
item=Buffer[out];
out=(out+1)%sizeofbuffer;
count=count-1;
signal(full);
}
Initialization()
{
sizeofbuffer=5;
in=1;
out=0;
count=0;
}
}
Producer Process Consumer Process
while(true) while(true)
{ {
printf(“enter item\n”); PC.delete();
scanf(“%d”,&item); }
PC.insert(item);
}
Classic problems of synchronization
Some processes named ‘readers’ only read data from the database.
At a time, any number of readers can read data from the database without any conflict.
But, when a writer is writing data then other writers and readers are not allowed to access the database.
Dining Philosopher’s Problem
There are 5 philosophers.
There are 5 plates and 5 spoons (chopsticks) and are placed on the table as shown in diagram.
A philosopher can eat food only when the two (left and right) chopsticks (spoons) are available for him.