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

Process Synchronization

Process synchronization coordinates the execution of processes to prevent two processes from accessing the same shared data or resources at the same time. A critical section is a segment of code that can only be accessed by one process at a time. Semaphores are used to implement process synchronization and solve the critical section problem in multiprocessing environments. A semaphore is an integer variable that processes access using wait and signal operations to coordinate access to shared resources.

Uploaded by

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

Process Synchronization

Process synchronization coordinates the execution of processes to prevent two processes from accessing the same shared data or resources at the same time. A critical section is a segment of code that can only be accessed by one process at a time. Semaphores are used to implement process synchronization and solve the critical section problem in multiprocessing environments. A semaphore is an integer variable that processes access using wait and signal operations to coordinate access to shared resources.

Uploaded by

Lata Sinha
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 9

1. What is process synchronization?

Process Synchronization is the task of coordinating the execution of processes in


a way that no two processes can have access to the same shared data and
resources.

It is specially needed in a multi-process system when multiple processes are


running together, and more than one processes try to gain access to the same
shared resource or data at the same time.

This can lead to the inconsistency of shared data. So the change made by one
process not necessarily reflected when other processes accessed the same shared
data. To avoid this type of inconsistency of data, the processes need to be
synchronized with each other.

2 What is critical section problem?

A critical section is a segment of code which can be accessed by a signal process at


a specific point of time. The section consists of shared data resources that
required to be accessed by other processes.

• The entry to the critical section is handled by the wait() function, and it is
represented as P().
• The exit from a critical section is controlled by the signal() function,
represented as V().

In the critical section, only a single process can be executed. Other processes,
waiting to execute their critical section, need to wait until the current process
completes its execution.

3. Write down an algorithm for 2-process solution of process


synchronization.

The processes share two variables: boolean flag[2]; int turn;

Initially flag[0] = flag[1] = false, and value of turn is immaterial (but either 0 or 1).

To enter the critical section, process Pi first sets flag[i] to be true and then sets
turn to the value of j, thereby asserting that if either process wishes to enter
critical section, it can do so. If both try to enter simultaneously, turn will be set to
both I and j at roughly same time. Only one of these assignments will last, the
other will occur, but will be overwritten immediately. The eventual value of turn
decides which of the two processes is allowed to enter its critical section first.

4. What is Semaphore? How it is implemented for n-process


solution?
Semaphore is used to solve the critical section problem and to achieve process
synchronization in the multiprocessing environment. A semaphore S is an integer
variable that, is accessed only through two standard operations: wait and signal.
The n processes share a semaphore, mutex, initialized to 1.
do{
wait(mutex);
critical section
signal(mutex);
reminder section
}while(1);

When a process executes the wait operation and finds that semaphore value is not
positive, it must wait. However, rather than waiting, the process can block itself. The
block operation places a process into a waiting queue associated with semaphore,
and the state of the process is switched to the waiting state.
void wait(semaphore S){
S.value--;
if(S.value < 0){
Add this process to S.L;
Block();
}
}
void signal(semaphore S){
S.value++;
if(S.value <= 0){
remove a process from S.L;
wakeup();
}
}

A process that is blocked, waiting on a semaphore S, should be restarted when


some other process executes Signal operation. The process is restarted by a
wakeup operation, which changes the process from waiting state to ready state. The
process is then placed in the ready queue.
5. What is Binary Semaphore?

They can only be either 0 or 1. They are also known as mutex locks, as the locks can
provide mutual exclusion. All the processes can share the same mutex semaphore
that is initialized to 1. Then, a process has to wait until the lock becomes 0. Then, the
process can make the mutex semaphore 1 and start its critical section. When it
completes its critical section, it can reset the value of mutex semaphore to 0 and
some other process can enter its critical section.

6. Describe the use of Semaphore by taking example of three


processes.

The canonical use of a semaphore is a lock associated with some resource so that
only one thread at a time has access to the resource. In the example below, we
have one piece of global data, the number of tickets remaining to sell, that we want
to coordinate the access by multiple threads. In this case, a binary semaphore
serves as a lock to guarantee that at most one thread is examining or changing the
value of the variable at any given time.

/** * Our main is creates the initial semaphore lock in an unlocked state
and sets up all of the ticket seller threads, and lets them run to
completion. They should all finish when all tickets have been sold. By
running with the -v flag, it will include the trace output from the thread
library. */

ticketsLock = SemaphoreNew("Tickets Lock", 1);

for (i = 0; i < NUM_SELLERS; i++) {

// give each thread a distinct name

ThreadNew(name, SellTickets, 0);

} RunAllThreads(); // Let all threads loose


SemaphoreFree(ticketsLock); // to be tidy, clean

/** * SellTickets * ---------- * This is the routine forked by each of the


ticket-selling threads. It will loop selling tickets until there are no
more tickets left to sell. Before accessing the global numTickets
variable, it acquires the ticketsLock to ensure that our threads don't step
on one another and oversell on the number of tickets. */

static void SellTickets(void) {

bool done = false;

int numSoldByThisThread = 0; // local vars are unique to each thread

while (!done) {

/** * imagine some code here which does something independent of


the other threads such as working with a customer to determine which
tickets they want. Simulate with a small random delay to get random
variations in output patterns. */ RandomDelay(500000, 2000000);

SemaphoreWait(ticketsLock); // ENTER CRITICAL SECTION

if (numTickets == 0) { // here is safe to access numTickets

done = true; // a "break" here instead of done variable

} else {

numTickets--;

numSoldByThisThread++;

} SemaphoreSignal(ticketsLock); // LEAVE CRITICAL SECTION

Another simple concurrency problem is simulating the process of hooking up


hydrogen atoms with oxygen atoms to form water molecules. Each atom is
represented by a separate thread, we will need to associate two hydrogen threads
with one oxygen thread to make a water molecule, then all three threads exit
together. We will use two general semaphores, one to count the number of hydrogen
threads and one for the number of oxygen threads. A hydrogen thread will wait to
consume one of the oxygen and then signal to raise the count of hydrogen to
communicate to the oxygen thread. An oxygen thread will wait for two hydrogen to
come ready and then signal the oxygen count twice to let them know oxygen is
ready. This is an example of a "rendezvous"—we are signaling a general
semaphore to record the action of one thread and another thread can wait on it to
meet up with it.

void main(int argc, char **argv) {

int i;

bool verbose = (argc == 2 && (strcmp(argv[1], "-v") == 0));

Semaphore oxygenReady, hydrogenReady; // semaphores used as counters

InitThreadPackage(verbose);

oxygenReady = SemaphoreNew("Oxygen Ready", 0);

hydrogenReady = SemaphoreNew("Hydrogen Ready", 0);

for (i = 0; i < NUM_WATER; i++)

ThreadNew(“Oxygen”, Oxygen, 2, oxygenReady, hydrogenReady);

for (i = 0; i < 2 * NUM_WATER; i++)

ThreadNew(“Hydrogen”, Hydrogen, 2, oxygenReady, hydrogenReady);

RunAllThreads();

static void Hydrogen(Semaphore oxygenReady, Semaphore hydrogenReady) {


SemaphoreWait(oxygenReady);

SemaphoreSignal(hydrogenReady);

static void Oxygen(Semaphore oxygenReady, Semaphore hydrogenReady) {


SemaphoreWait(hydrogenReady);

SemaphoreWait(hydrogenReady);

SemaphoreSignal(oxygenReady);

SemaphoreSignal(oxygenReady);

Library Analogy:
Suppose a library has 10 identical study rooms, to be used by one student at a time. Students
must request a room from the front desk if they wish to use a study room. If no rooms are free,
students wait at the desk until someone relinquishes a room. When a student has finished using
a room, the student must return to the desk and indicate that one room has become free.
In the simplest implementation, the clerk at the front desk knows only the number of free rooms
available, which they only know correctly if all of the students actually use their room while
they've signed up for them and return them when they're done. When a student requests a room,
the clerk decreases this number. When a student releases a room, the clerk increases this
number. The room can be used for as long as desired, and so it is not possible to book rooms
ahead of time.
In this scenario the front desk count-holder represents a counting semaphore, the rooms are the
resource, and the students represent processes/threads.
The value of the semaphore in this scenario is initially 10, with all rooms empty.
When a student requests a room, they are granted access, and the value of the semaphore is
changed to 9.
After the next student comes, it drops to 8, then 7 and so on.
If someone requests a room and the current value of the semaphore is 0,[2] they are forced to
wait until a room is freed (when the count is increased from 0). If one of the rooms was released,
but there are several students waiting, then any method can be used to select the one who will
occupy the room.
Student needs to inform the clerk about releasing their room only after really leaving it.

7. How semaphore can be used to solve problem of Producer-


Consumer Problem, Dinning Philosopher and Reader-Writer
Problem?

Producer-Consumer Problem

The producer consumer problem is a synchronization problem. There is a fixed size


buffer and the producer produces items and enters them into the buffer. The
consumer removes the items from the buffer and consumes them.

A producer should not produce items into the buffer when the consumer is consuming
an item from the buffer and vice versa. So the buffer should only be accessed by the
producer or consumer at a time.
The producer consumer problem can be resolved using semaphores. The codes for
the producer and consumer process are given as follows:

Producer Process
The code that defines the producer process is given below:
do {

. PRODUCE ITEM

wait(empty);

wait(mutex);

. PUT ITEM IN BUFFER

signal(mutex);

signal(full);

} while(1);

Consumer Process
The code that defines the consumer process is given below:

do {

wait(full);

wait(mutex); .

. REMOVE ITEM FROM BUFFER

signal(mutex);

signal(empty);

. CONSUME

ITEM .

} while(1);
The Dining Philosopher Problem –
The Dining Philosopher Problem states that K philosophers 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.
Semaphore Solution to Dining Philosopher –
do{
wait(chopstick[i]);
wait(chopstick[(i+1)%5]);

Eat

signal(chopstick[i]);
signal(chopstick[i+1]%5);

Think

}while(1);
A philosopher tries to grab the chopstick by executing a wait operation on that
semaphore, she releases her chopsticks by executing the signal operation on
appropriate semaphores. Thus the shared data are semaphore chopstick[5]; where
all the elements are initialized to 1.

READERS WRITER PROBLEM USING SEMAPHORES


A data object such as file is to be shared among several concurrent processes.
Some processes are interested only in reading are readers, and to the rest as
writers. If a writer and some other process access the shared object simultaneously,
chaos may ensue. To ensure that difficulties do not arise, the writers should have
exclusive access to the shared object. This synchronization problem is readers-
writers problem.
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);
signal(mutex);
}while(true);
Thus, the semaphore ‘wrt‘ is queued on both readers and writers in a manner such
that preference is given to readers if writers are also there. Thus, no reader is waiting
simply because a writer has requested to enter the critical section.

You might also like