Unit 3 Presentation
Unit 3 Presentation
Mutual Exclusion
Process/thread Synchronization and Mutual Exclusion: Principles of
Concurrency, Requirements for Mutual Exclusion, Mutual Exclusion: Hardware
Support, Operating System Support (Semaphores and Mutex), Programming
Language Support (Monitors). Classical synchronization problems:
Readers/Writers Problem, Producer and Consumer problem, Inter-process
communication (Pipes, shared memory: system V).
Deadlock
Principles of Deadlock, Deadlock Modeling, Strategies to deal with deadlock:
The Ostrich Algorithm, Deadlock Prevention, Deadlock Avoidance, Deadlock
detection and recovery, An Integrated Deadlock Strategy, Example: Dining
Philosophers Problem. Unix Concurrency Mechanism
Department of Information Technology, VIIT, Pune-48
Principles of Concurrency
-------- --------
-------- --------
Progress
Bounded waiting
Interested[process]=TRUE;
Turn=process
While(interested[other]==TRUE && turn==process)
}
//*********Critical section**********//
Exit_section(process)
{
Interested[process]=false;
}
Department of Information Technology, VIIT, Pune-48
Solution – 2: Semaphore
• One of the method to remove the race condition
• Technique to manage concurrent processes by using a simple
integer value, which is known as a semaphore.
• Semaphore is simply an integer variable that is shared between
threads.
• This variable is used to solve the critical section problem and to
achieve process synchronization
• Two types-
• 1. Counting Semaphore – semaphore value can vary from -∞ to
+∞
• 2. Binary Semaphore - – semaphore value can vary from 0 to 1
1.Binary Semaphore
• Value of the semaphore can only be either 0 or 1.
• If the value of Semaphore is 1, the process can enter into the critical section ,
• If the value is 0, the process cannot enter into the critical section of the code.
• When a process is using the critical section, we change the Semaphore value to 0,
• When a process is not using it, or we can allow a process to access the critical
section, we change the value of semaphore to 1.
• Binary semaphore is also called mutex lock.
Down(semaphore s) Up (semaphore s)
{ {
s.value=s.value-1 s.value=s.value+1
If(s.value<0)
If(s.value<=0)
{
Suspend()
{
Sleep() Select a process from suspend list
} Wakeup()
Else }
Return }
}
{
initializing_code;
}
• The producer should generate data only if the buffer is not full.
When the buffer is filled, the producer should not be able to add
any more data to it.
• When the buffer is not empty, the consumer can consume the
data. The consumer should not be able to take any data from the
buffer if it is empty.
• The buffer should not be used by both the producer and the
consumer at the same time.
Buffer has total 8 spaces out of which the first 5 are filled,
in = 5(pointing next empty position) and
out = 0(pointing first filled position).
Let's start with the producer who wanted to produce an element " F ",
according to code it will enter into the producer() function, while(1) will
always be true, itemP = F will be tried to insert into the buffer, before
that while(count == n); will evaluate to be False.
• Consumer Code:
• Now starting consumer who wanted to consume the first element " A
", according to code it will enter into the consumer() function, while(1)
will always be true, while(count == 0); will evaluate to be False( since
the count is still 5, which is not equal to 0.
itemC = Buffer[out]→ itemC = A ( since out is 0)
• out = (out + 1) mod n → (0 + 1)mod 8→ 1, therefore out = 1( first filled
position)
• A is removed now
• After removal of A, Buffer look like this
• Where out = 1, and in = 6
void *producer(void *pno) int a[5] = {1,2,3,4,5}; // used for numbering the producer and consumer
{
int item; for(int i = 0; i < 5; i++)
for(int i = 0; i < MaxItems; i++) {
{ pthread_create(&pro[i], NULL, (void *)producer, (void *)&a[i]);
item = rand(); // Produce a random item }
sem_wait(&empty);//initialized with 1 (entry code) for(int i = 0; i < 5; i++)
//wait, if there is no empty slots {
//The sem_wait() function decrements by one the value of pthread_create(&con[i], NULL, (void *)consumer, (void *)&a[i]);
//the semaphore. The semaphore will be decremented when }
//its value is greater than zero. If the value of the
//semaphore is zero, then the current thread will block for(int i = 0; i < 5; i++)
//until the semaphore's value becomes greater than zero. {
pthread_join(pro[i], NULL);
pthread_mutex_lock(&mutex); //if empty is > 0 acquire semaphore(lock) }
//Critical section starts for(int i = 0; i < 5; i++)
buffer[in] = item; {
printf("Producer %d: Inserted the item %d at %d\n", *((int *)pno),buffer[in],in); pthread_join(con[i], NULL);
in = (in+1)%BufferSize; }
//Critical section ends
pthread_mutex_unlock(&mutex);//release semaphore(unlock) pthread_mutex_destroy(&mutex);//This destroys the mutex object *mutex.
sem_post(&full); //same as signal operation(exit operation) sem_destroy(&empty);
//sem_post() increments the semaphore If the semaphore's value becomes greater sem_destroy(&full);
//than zero,then another process or thread blocked in a return 0;
//sem_wait call will be woken up and proceed to lock the
//semaphore. }
}
}
void *consumer(void *cno)
{
for(int i = 0; i < MaxItems; i++)
{
Department of Information Technology, VIIT, Pune-48
Readers/Writers Problem
• There is a shared resource which should be accessed by multiple processes.
• There are two types of processes in this context. They
are reader and writer.
• Any number of readers can read from the shared resource simultaneously.
• But only one writer can write to the shared resource.
• When a writer is writing data to the resource, no other process can access
the resource.
• A writer cannot write to the resource if there are non zero number of
readers accessing the resource at that time.
• If a writer wants to write to the resource, it must wait until there are no
readers currently accessing that resource.
Int rc=0
Semaphore m=1, db=1 Down(m)
Void reader(void) //reader executes this rc - -
{ code If(rc==0) then up(db)
While(true) { Up(m)
Down(m) //same as wait() //Process data
rc++ }
If(rc==1) then down(db) }
Up(m) //same as signal void writter(void){
While(true){
Critical
section down(db)
Critical
section
//exit code starts
Up(db)
Department of Information}}Technology, VIIT, Pune-48
Inter process Communication
Inter-Process Communication is the mechanism by which cooperating process share data and
information. The mechanism that will allow them to exchange data and information are the
following:–
Shared memory
Message Passing
Pipes
Fd [0]
Fd [1]
• Mutual Exclusion: Only one process can use a resource at any given time
i.e. the resources are non-sharable.
• Hold and wait: A process is holding at least one resource at a time and is
waiting to acquire other resources held by some other process.
• No preemption: The resource can be released by a process voluntarily i.e.
after execution of the process.
• Circular Wait: A set of processes are waiting for each other in a circular
fashion. For example, lets say there are a set of processes {P0 P1, P2, P3}
such that P0depends on P1, P1depends on P2, P2depends on P3and P3
depends on P0.
• This creates a circular relation between all these processes and they have to
wait forever to be executed.
process P[i]
while true do
{
THINK();
takeFork(CHOPSTICK [i]); //left fork
takeFork (CHOPSTICK [i+1 mod 5]); //Right
EAT();
ReturnFork (CHOPSTICK [i]);
ReturnFork (CHOPSTICK [i+1 mod 5]);
} This works fine when the processes are executed serially, one after another.
But may form a race condition if two or more processes executes
concurrently
Department of Information Technology, VIIT, Pune-48
Dining Philosophers Problem
P0S0 & S1
P1 S1 & S2
P2S2 & S3
P3S3 & S4
P4 S4 & S0
process P[i]
P0S0 & S1 while true do
P1 S1 & S2 {
P2S2 & S3 THINK();
P3S3 & S4 down/wait (CHOPSTICK [i]);
down/wait (CHOPSTICK [i+1 mod 5]);
P4 S4 & S0
EAT();
S0 & S4 up/Signal (CHOPSTICK [i]);
up/Signal (CHOPSTICK [i+1 mod 5]);
}