Critical Section Problem

Download Report

Transcript Critical Section Problem

Process Synchronization
Topics:
1.Background
2.The critical-section problem
3.Semaphores
4.Critical Regions
5.Monitors
Background
Concurrent access to Data may result in
data inconsistency
To maintain data consistency we should
have orderly execution of co-operating
processes
In the bounded buffer example, what
happens I we maintain a counter to keep
track of number of items produced
common to producer and consumer
Bounded Buffer
Shared Data: buffer[n],in,out,counter
Producer Process:
repeat
produce an item in nextp
while counter==n wait
buffer[in]=nextp;in=(in+1)%n;counter++;
until false
Bounded Buffer (continued)
Consumer Process
repeat
while counter==0 do no-op
nextc=buffer[out];
counter--; consume item nextc
until false
Statements counter++ and counter-- have to
be done atomically - no interrupt
Critical Section Problem
n processes competing to use shared data
Each process has a code segment called
critical section in which shared data is
accessed
Issue: When one process is in critical
section, no other process is in critical
section
Structure of Process
repeat
Critical section
Remainder section
until false
Solution to Critical Section
Problem
1. Mutual Exclusion: No two processes are in
the critical section at the same time.
2. Progress: If no process is in the critical
section and a process wishes to enter, that
process cannot be postponed indefinitely
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 cs and
that process is granted.
Initial Attempts to solve
Problem
Only 2 Processes P_0 and P_1
General Structure of Process P_j (other is P_i)
repeat
entry section; critical section;
exit section;remainder section;
until false;
Processes may share some common variables
to synchronize their actions.
Algorithm 1
Shared variables: int turn /* turn=j it P_jth
turn*/
Process P_j
repeat
while (turn <> j) wait
critical section;
turn=I; remainder section;
umtil false
Algorithm 2
Shared variables: boolean flag[2] /*flag[j]=true
means jth turn */
Process P_j
entry section: flag[j]=true; while (flag[i]) wait;
exit section: flag[j]=false;
As before satisfies mutual exclusion but no
progress.
Algorithm 3
Shared variables: flag[2] , turn;
Process P_j
entry section: flag[j]=true; turn=j; while (flag[i]
and turn==i) wait;
exit section: flag[j]=false;
Satisfies all three requirements- critical thing to
note is turn is a shared variable.
Bakery Algorithm
Critical Section for n processors
Before entering the critical section, process
receives a number. Holder of the smallest
number enters its critical section.
If processes P_i and P_j receive the same
number, if i<j, then P_i is served first else p_j is
served.
Numbering scheme always generates numbers
in non-decreasing order.
Bakery Algorithm (continued)
We use lexicographic order. (a,b) < (c,d) is
either a< c or a=c b< d.
Shared data: Boolean choosing[n]
int number[n]
they are initialized to false and 0 resply.
Bakery Algorithm (continued)
Enter section:
choosing[j] = true;
number[j]=max of numbers +1
choosing[j]=false;
for (k=0;k<n;k++) {
while(choosing[k]) wait;
while(number[k] <>0) and
(number[k],k) <number[j],j) wait;
}Leave Section: number[j]=0;
Synchronization Hardware
Test and modify the content of a word atomically
boolean Test-and-set(boolean target){
Test-and-set = target; target = true;
}
Mutual Exclusion with Testand-set
Shared data: boolean lock (initially false)
Process P_j:
enter section: while (Test-and-lock) wait;
leave section: lock = false;
Semaphore
Synchronization tool that does not require busy
wait
Semaphore S - integer variable
can only be accessed via two indivisible atomic
operations
wait(s): while (s <=0) no-op; s = s-1;
signal(s): s=s+1;
Critical section for n processes
Shared Variable: semaphore mutex;
initial value of mutex=1;
entersection: wait(mutex);
leavesection: signal(mutex);
Semaphore Implementation
Semaphore as a struct
typedef semaphore struct { int value;
ProcessList L }
Two Simple operations:
block - suspends the process that invokes it
wakeup(P) resumes the execution of a
blocked process P
Semaphore Implementation
(continued)
Wait(S) :
S.value--; if (S.value<0) { add this process
to S.l; block;}
Signal(S):
S.value++; if (S.value<=0) {remove a
process from P from S.L; wakeup(P);}
Implementation (continued)
Wait(S) :
S.value--; if (S.value<0) { add this process
to S.l; block;}
Signal(S):
S.value++; if (S.value<=0) {remove a
process from P from S.L; wakeup(P);}
Semaphore as General
Synchronization Tool
Execute B in P_j only after A is executed in
P_i
Use semaphore flag initialized to 0
code P_i: A ; signal(flag)
Code P_j: wait(flag); B;
Deadlock and Starvation
Deadlock - two or more processes are
waiting for indefinitely for an event that can
be caused by only one of the waiting
processes. S and Q are semaphores.
P_0: wait(S);wait(Q); ..signal(S);signal(Q);
P_1:wait(Q);wait(S);..;signal(Q);signal(S);
Starvation: A process may never be
removed from the semaphore queue .
Two Types of Semaphores
•Counting Semaphore - integer value can
range over an unrestricted domain
•Binary Semaphore - integer value can range
from 0 to 1 - easier to implement.
•Can implement (simulate) a counting
semaphore using a binary semaphore.
Implementing S as a binary
Semaphore
Data Structures:
binary_semaphore s1,s2,s3;
int c;
Initialization
s3=s1=1; s2=0;
c=initial value of semaphore
Implementing S (continued)
Wait operation
wait(s3);wait(s1);c=c-1; if (c<0)
{signal(s1);wait(s2); else {signal(s1);}
signal(s3);
Signal Operation: wait(s1); c=c+1; if (c<=0)
{signal(s2);} signal(s1);
Classical Problems of
Synchronization
Bounded Buffer Problem
Readers and writers Problem
Dining Philosopher
Bounded Buffer Problem
Shared Data
String Item;
String buffer[];
semaphore full,empty,mutex;
item nextp,nextc;
full=0;empty=n;mutex=1
Producer Process
Repeat
{ produce an item in nextp;
wait(empty);wait(mutex);
add nextp to buffer; signal(mutex);
signal(full);
} until false;
Consumer Process
Repeat {
wait(full);wait(mutex);
remove an item from buffer in nextc;
signal(mutex); signal(empty);
consume an item in nextc;
} until false;
Readers and Writers Problem
Shared Data: Semaphore mutex,wrt;(=1)
int readcount;
Writer Process:
wait(wrt); write; signa(wrt);
Reader Process
Entersection:
wait(mutex); readcount++;
if (readcount==1) wait(wrt);
signal(mutex);
leavesection:
wait(mutex);readcount-; if(reacount==0)
signal(wrt); signal(mutex);
Dining Philosopher Problem
Shared data: Semaphore chopstick[5](=1);
Philosopher_j
entersection: wait(chopstick[j]);
wait(chopstick[(j+1)%5]);
Leavesection: signal(chopstick[j]);
signal(chopstick[(j+1)%5]);