0% found this document useful (0 votes)
15 views

Chapter-2 (OS) Continued

Uploaded by

shubhamjha160704
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views

Chapter-2 (OS) Continued

Uploaded by

shubhamjha160704
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 11

Critical Section problem

a critical section refers to a segment of code that is executed by


multiple concurrent threads or processes, and which accesses
shared resources. These resources may include shared memory,
files, or other system resources that can only be accessed by one
thread or process at a time to avoid data inconsistency or race
conditions.

1. The critical section must be executed as an atomic


operation, which means that once one thread or process
has entered the critical section, all other threads or
processes must wait until the executing thread or process
exits the critical section. The purpose of synchronization
mechanisms is to ensure that only one thread or process
can execute the critical section at a time.
2. The concept of a critical section is central to
synchronization in computer systems, as it is necessary to
ensure that multiple threads or processes can execute
concurrently without interfering with each other. Various
synchronization mechanisms such as semaphores,
mutexes, monitors, and condition variables are used to
implement critical sections and ensure that shared
resources are accessed in a mutually exclusive manner.

Critical Section:
When more than one threads try to access the same code segment
that segment is known as the critical section. The critical section
contains shared variables or resources that need to be
synchronized to maintain the consistency of data variables.
In simple terms, a critical section is a group of
instructions/statements or regions of code that need to be
executed atomically.
In concurrent programming, if one thread tries to change the value
of shared data at the same time as another thread tries to read the
value (i.e., data race across threads), the result is unpredictable.
The access to such shared variables (shared memory, shared files,
shared port, etc.) is to be synchronized.

Although there are some properties that should be followed if any


code in the critical section:
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 some processes wish to enter their critical sections,
then only those processes that are not executing in their
remainder sections can participate in deciding which will
enter its critical section next, and this selection cannot be
postponed indefinitely.
3. Bounded Waiting: There exists a bound, or limit, 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.

The use of critical sections in a program can cause a number of


issues, including:
1. Deadlock: When two or more threads or processes wait for
each other to release a critical section, it can result in a
deadlock situation in which none of the threads or processes
can move. Deadlocks can be difficult to detect and resolve,
and they can have a significant impact on a program’s
performance and reliability.
2. Starvation: When a thread or process is repeatedly
prevented from entering a critical section, it can result in
starvation, in which the thread or process is unable to
progress. This can happen if the critical section is held for an
unusually long period of time, or if a high-priority thread or
process is always given priority when entering the critical
section.
3. Overhead: When using critical sections, threads or processes
must acquire and release locks or semaphores, which can
take time and resources. This may reduce the program’s
overall performance.
Semaphores in Process Synchronization
Semaphores are just normal variables used to coordinate the
activities of multiple processes. They are used to enforce mutual
exclusion, avoid race conditions, and implement synchronization
between processes.
The process of using Semaphores provides two operations: wait (P)
and signal (V). The wait operation decrements the value of the
semaphore, and the signal operation increments the value of the
semaphore. When the value of the semaphore is zero, any process
that performs a wait operation will be blocked until another process
performs a signal operation.
Semaphores are used to implement critical sections, which are
regions of code that must be executed by only one process at a
time. By using semaphores, processes can coordinate access to
shared resources, such as shared memory or I/O devices.
When a process performs a wait operation on a semaphore, the
operation checks whether the value of the semaphore is >0. If so, it
decrements the value of the semaphore and lets the process
continue its execution; otherwise, it blocks the process on the
semaphore. A signal operation on a semaphore activates a process
blocked on the semaphore if any, or increments the value of the
semaphore by 1. Due to these semantics, semaphores are also
called counting semaphores. The initial value of a semaphore
determines how many processes can get past the wait operation.

Semaphores are of two types:


1. Binary Semaphore –
This is also known as a mutex lock. It can have only two
values – 0 and 1. Its value is initialized to 1. It is used to
implement the solution of critical section problems with
multiple processes.
2. Counting Semaphore –
Its value can range over an unrestricted domain. It is used
to control access to a resource that has multiple instances
Some points regarding P and V operation:
1. P operation is also called wait, sleep, or down operation,
and V operation is also called signal, wake-up, or up
operation.
2. Both operations are atomic and semaphore(s) is always
initialized to one. Here atomic means that variable on
which read, modify and update happens at the same
time/moment with no pre-emption i.e., in-between read,
modify and update no other operation is performed that
may change the variable.
3. A critical section is surrounded by both operations to
implement process synchronization. The critical section
of Process P is in between P and V operation.
Advantages of Semaphores:
 A simple and effective mechanism for process
synchronization
 Supports coordination between multiple processes
 Provides a flexible and robust way to manage shared
resources.
 It can be used to implement critical sections in a program.
 It can be used to avoid race conditions.
Disadvantages of Semaphores:
 It Can lead to performance degradation due to overhead
associated with wait and signal operations.
 Can result in deadlock if used incorrectly.
 It can be difficult to debug and maintain.
 It can be prone to race conditions and other
synchronization problems if not used correctly.

Producer Consumer Problem using


Semaphores
Producer consumer problem is a classical synchronization problem.

Problem Statement – We have a buffer of fixed size. A producer


can produce an item and can place in the buffer. A consumer can
pick items and can consume them. We need to ensure that when a
producer is placing an item in the buffer, then at the same time
consumer should not consume any item. In this problem, buffer is
the critical section.
To solve this problem, we need two counting semaphores – Full and
Empty. “Full” keeps track of number of items in the buffer at any
given time and “Empty” keeps track of number of unoccupied
slots.

Initialization of semaphores –
mutex = 1 //binary semaphore
Full = 0 // Initially, all slots are empty. Thus full slots are 0
Empty = n // All slots are empty initially.

Solution for Producer –


do{
//produce an item
wait(empty);
wait(mutex);
//critical section
signal(mutex);
signal(full);
}while(true)

When producer produces an item then the value of “empty” is


reduced by 1 because one slot will be filled now. The value of
mutex is also reduced to prevent consumer to access the buffer.
Now, the producer has placed the item and thus the value of “full”
is increased by 1. The value of mutex is also increased by 1
because the task of producer has been completed and consumer
can access the buffer.

Solution for Consumer –


do{
wait(full);
wait(mutex);
// consume item from buffer(critical section)
signal(mutex);
signal(empty);
}while(true)

As the consumer is removing an item from buffer, therefore the


value of “full” is reduced by 1 and the value is mutex is also
reduced so that the producer cannot access the buffer at this
moment. Now, the consumer has consumed the item, thus
increasing the value of “empty” by 1. The value of mutex is also
increased so that producer can access the buffer now.

Readers-Writers Problem
Consider a situation where we have a file shared between many
people.
 If one of the person tries editing the file, no other person
should be reading or writing at the same time, otherwise
changes will not be visible to him/her.
 However, if some person is reading the file, then others
may read it at the same time.

Problem parameters: that


 One set of data is shared among a number of processes
 Once a writer is ready, it performs its write. Only one writer
may write at a time
 If a process is writing, no other process can read it
 If at least one reader is reading, no other process can write
 Readers may not write and only read

Solution when Reader has the Priority over Writer:


Here priority means, no reader should wait if the share is currently
opened for reading.
Three variables are used: mutex, wrt, readcnt to implement
solution:
1. semaphore mutex, wrt; // semaphore mutex is used to
ensure mutual exclusion when readcnt is updated i.e.
when any reader enters or exit from the critical section and
semaphore wrt is used by both readers and writers
2. int readcnt; // readcnt tells the number of processes
performing read in the critical section, initially 0

Functions for semaphore :


– wait() : decrements the semaphore value.
– signal() : increments the semaphore value.

Writer process:
1. Writer requests the entry to critical section.
2. If allowed i.e. wait() gives a true value, it enters and
performs the write. If not allowed, it keeps on waiting.
3. It exits the critical section.

do {
// writer requests for critical section
wait(wrt);

// performs the write

// leaves the critical section


signal(wrt);
} while(true);

Reader process:
1. Reader requests the entry to critical section.
2. If allowed:
 it increments the count of number of readers inside
the critical section. If this reader is the first reader
entering, it locks the wrt semaphore to restrict the
entry of writers if any reader is inside.
 It then, signals mutex as any other reader is
allowed to enter while others are already reading.
 After performing reading, it exits the critical
section. When exiting, it checks if no more reader
is inside, it signals the semaphore “wrt” as now,
writer can enter the critical section.
3. If not allowed, it keeps on waiting.
do {
// Reader wants to enter the critical section
wait(mutex);

// The number of readers has now increased by 1


readcnt++;

// there is atleast one reader in the critical section


// this ensure no writer can enter if there is even one
reader
// thus we give preference to readers here
if (readcnt==1)
wait(wrt);

// other readers can enter while this current reader is


inside
// the critical section
signal(mutex);

// current reader performs reading here


wait(mutex); // a reader wants to leave

readcnt--;

// that is, no reader is left in the critical section,


if (readcnt == 0)
signal(wrt); // writers can enter

signal(mutex); // reader leaves


} while(true);

Dining Philosopher Problem:


The Dining Philosopher Problem states that K philosophers are
seated around a circular table with one chopstick between each
pair of philosophers. There is one chopstick between each
philosopher. A philosopher may eat if he can pick up the two
chopsticks adjacent to him. One chopstick may be picked up by any
one of its adjacent followers but not both. The Dining Philosopher
Problem is a classic synchronization problem in computer science
that involves multiple processes (philosophers) sharing a limited
set of resources (forks) in order to perform a task (eating). In order
to avoid deadlock or starvation, a solution must be implemented
that ensures that each philosopher can access the resources they
need to perform their task without interference from other
philosophers.

Semaphore Solution to Dining Philosopher:


Each philosopher is represented by the following pseudocode:
process P[i]
while true do
{ THINK;
PICKUP(CHOPSTICK[i], CHOPSTICK[i+1 mod 5]);
EAT;
PUTDOWN(CHOPSTICK[i], CHOPSTICK[i+1 mod 5])
}
There are three states of the philosopher: THINKING, HUNGRY,
and EATING. One common solution to the Dining Philosopher
Problem uses semaphores, a synchronization mechanism that can
be used to control access to shared resources. In this solution, each
fork is represented by a semaphore, and a philosopher must
acquire both the semaphore for the fork to their left and the
semaphore for the fork to their right before they can begin eating.
If a philosopher cannot acquire both semaphores, they must wait
until they become available.
The steps for the Dining Philosopher Problem solution using
semaphores are as follows:
1. Initialize the semaphores for each fork to 1 (indicating
that they are available).
2. initialize a binary semaphore (mutex) to 1 to ensure that
only one philosopher can attempt to pick up a fork at a
time.
3. For each philosopher process, create a separate thread
that executes the following code:
 While true:
o Think for a random amount of time.
o Acquire the mutex semaphore to ensure that only one
philosopher can attempt to pick up a fork at a time.
o Attempt to acquire the semaphore for the fork to the left

o If successful, attempt to acquire the semaphore for the


fork to the right.
o If both forks are acquired successfully, eat for a random
amount of time and then release both semaphores.
o If not successful in acquiring both forks, release the
semaphore for the fork to the left (if acquired) and then
release the mutex semaphore and go back to thinking.

4. Run the philosopher threads concurrently.

By using semaphores to control access to the forks, the Dining


Philosopher Problem can be solved in a way that avoids deadlock
and starvation. The use of the mutex semaphore ensures that only
one philosopher can attempt to pick up a fork at a time, while the
use of the fork semaphores ensures that a philosopher can only eat
if both forks are available.

You might also like