Semaphore mechanism for process synchronization (pv operation) and three typical synchronization problems

Source: Internet
Author: User

In the previous blog (critical region of Process Synchronization and the Peterson algorithm), we have explained the critical zone, critical resource, and lock mechanism in detail, leaving a problem, that is, the lock mechanism can only judge whether the critical resources are occupied, so it solves the mutex problem, but he cannot determine whether the previous process is complete, so he cannot be used in the synchronization problem. The following describes how the semaphore mechanism solves this problem.

1. semaphore mechanism the semaphore mechanism uses pv operations to process semaphores.

What is semaphores? The data structure of semaphore is a value and a pointer. The Pointer Points to the next process waiting for the semaphore. The semaphore value is related to the usage of the corresponding resource.

When its value is greater than 0, it indicates the number of currently available resources;

When its value is less than 0, its absolute value indicates the number of processes waiting to use the resource.

Note that the semaphore value can only be changed by the PV operation.

Generally, when the semaphores S30, S indicates the number of available resources. Executing a P operation means that one unit resource is allocated to the request. Therefore, the value of S is reduced by 1. When S <0, no resources are available. The requester must wait for other processes to release such resources, it can run. Executing a V operation means releasing a unit resource. Therefore, the value of S is increased by 1. If S reaches 0, some processes are waiting for this resource, therefore, you need to wake up a waiting process to run it.
2. PV operation What is PV?

P operation (wait): Apply for a unit resource and the process enters

Classic pseudocode

Wait (S) {while (s <= 0) // wait cyclically if no resources exist; S --;}

 

V Operation (signal): releases a unit of resources and processes

signal(S){S++ ;}
P operation (wait): Apply for a unit resource, and the process enters the v Operation (signal): release a unit resource. The meaning of the PV operation is as follows: a pv operation consists of a P operation primitive and a V Operation primitive (the primitive is an uninterrupted process). The PV operation on semaphores is defined as follows:
P (S): ① reduce the semaphore S value by 1, that is, S = S-1;
② If S <= 0, the process continues to run; otherwise, the process is set to the waiting status and is discharged into the waiting queue.
V (S): ① Add 1 to the semaphore S value, that is, S = S + 1;
② If S> 0, the process continues; otherwise, the first process in the queue is released waiting for the semaphore.
The significance of PV operations: We use semaphores and PV operations to synchronize and mutex processes. The PV operation is a low-level communication of processes.

Note the following when using the PV operation to achieve process mutex:
(1) The P and V operations that are mutually exclusive to the user in each program must appear in pairs. First, P operations are performed to enter the critical section, and then V operations are performed to output the critical section. If multiple branches exist, check their pairs carefully.
(2) P and V operations should be respectively close to the head and tail of the critical section. The code of the critical section should be as short as possible and there should be no endless loops.
(3) The initial value of mutex semaphores is generally 1.

3. Three Typical synchronization problems we mentioned above the semaphore mechanism. Below we will explain how to use the semaphore and PV operations to solve several typical synchronization problems. A. producer-consumer (buffer issue) the producer-consumer question (producer-consumerproblem) refers to the use of buffer resources when several processes exchange data through a limited shared buffer. Assume that the "producer" process constantly writes human data (that is, production data) to the shared buffer, while the "consumer" process constantly reads data (that is, consumption data) from the shared buffer. There are n shared buffer zones; only one process can operate on the shared buffer at any time. All producers and consumers must coordinate to complete operations on the shared buffer.

Producer process structure:

do{     wait(empty) ;     wait(mutex) ;         add nextp to buffer         signal(mutex) ;     signal(full) ;}while(1) ;

Consumer process structure:
do{     wait(full) ;     wait(mutex) ;         remove an item from buffer to nextp         signal(mutex) ;     signal(empty) ;}while(1) ;

We can regard n buffer blocks in the shared buffer zone as shared resources. The buffer blocks of producer writer data become available resources for consumers, and the buffer blocks after consumers read data become available resources for producers. Therefore, you can set three semaphores: full, empty, and mutex. Where: full indicates the number of buffer blocks with data, the initial value is 0; empty indicates that the initial value of the number of empty buffer blocks is n; mutex is used to access the buffer zone, and the initial value is 1. In fact, the relationship between full and empty exists as follows: full + empty = N
Note: The order of P operations in each process is important. Each process must first check its own number of resources before applying for mutex operations on the entire buffer after it is sure that there are available resources; otherwise, A deadlock may occur when you apply for a mutex operation on the entire buffer zone and then apply for the corresponding buffer block resources. When a deadlock occurs, after a mutex operation on the entire buffer zone is applied, the corresponding buffer block resource is discovered. At this time, it is impossible to discard the occupation of the entire buffer zone. If the AND semaphore set is used, the corresponding entry AND exit zones are very simple. If the producer's entry zone is Swait (empty, mutex), the exit zone is Ssignal (full, mutex ).
B. Author reader problem reader-Writer Problem (readers-writersproblem) refers to the issue where multiple processes perform read and write operations on a shared resource. Assume that the "Reader" process can read shared resources, and the "Writer" process can write shared resources. At any time, the "Writer" can only read one shared resource, the "Reader" allows multiple readers. That is, the read/write restrictions on shared resources include: "read-write, mutex," Write-write ", and" Read-read.


We can think that shared resources should be mutually exclusive access between writers and the first reader, and mutual access is not required for later readers. Therefore, you can set two semaphores Wmutex, Rmutex, and a public variable Rcount. Where: Wmutex indicates "Write allowed", the initial value is 1; The Public variable Rcount indicates the number of processes being read, and the initial value is 0; Rmutex indicates the mutex operation on Rcount, the initial value is 1.
In this example, we can see the nested use of the critical resource access process. In the reader algorithm, a critical resource access process is nested in the entry and exit areas.

A general "semaphore set" mechanism can also be used to solve the reader's issue. If we add a limit to the preceding read/write operation limit: the number of "readers" that can be read at the same time can be up to R. In this case, you can set two semaphores Wmutex and Rcount. Where: Wmutex indicates "Write allowed", initial value is Rcount, indicating "Number of allowed readers", and initial value is R. It is a reader-by-writer algorithm that uses the general "semaphore set" mechanism. C. Dining by philosophers

(1) under what circumstances cannot all five philosophers eat?
Consider the following two methods:
A.
Algorithm Description:
Void philosopher (int I)/* I: philosopher ID, from 0 to 4 */{while (TRUE) {think (); /* philosophers are thinking */take_fork (I);/* Take chopsticks on the left */take_fork (I + 1) % N);/* Take chopsticks on the left; % is modulo operation */eat ();/* eat */put_fork (I);/* put the left chopsticks back to the table */put_fork (I + 1) % N);/* put the chopsticks on the right back to the table */}}


Analysis: If all philosophers pick up the chopsticks on the left at the same time, they can see that the chopsticks on the right are unavailable, and they all put down the chopsticks on the left,
Wait for a while, and at the same time pick up the chopsticks on the left side, so that it will always be repeated. In this case, all programs are
It runs indefinitely, but it cannot make any progress, that is, hunger occurs, and all philosophers cannot eat.
B.
Algorithm Description:
After obtaining the chopsticks on the left side, check whether the chopsticks on the right are available. If not, put down the chopsticks on the left,
Repeat the entire process for a while.
Analysis: in the following situations, all philosophers start the algorithm at the same time and pick up the chopsticks on the left.
Child, and you can see that the chopsticks on the right are not available, and put down the chopsticks on the left, wait for a while, and at the same time pick up the chopsticks on the left ...... So
This will always be repeated. In this case, all programs are running, but no progress can be made, that is, hunger,
All philosophers cannot eat.
(2) describe an algorithm that no one is starved to death (never getting chopsticks.
Four implementation methods (A, B, C, and D) are considered ):
A. Principle: at most four philosophers can eat at the same time to ensure that at least one philosopher can eat at the same time.
Let out the two chopsticks he used, so that more philosophers can eat. The following uses room as the semaphore and only allows
A total of four philosophers can eat at the same time, so that at least one philosopher can eat at the same time.
The philosophers of the restaurant enter the waiting queue of the room. According to the FIFO principle, they will always enter the dining room, so they will not
Starvation and deadlock occur.
Pseudo code:
Semaphore chopstick [5] = {1, 1, 1}; semaphore room = 4; void philosopher (int I) {while (true) {think (); wait (room ); // request to enter the room for meal wait (chopstick [I]); // request the chopsticks wait (chopstick [(I + 1) % 5]) on the left side; // request the chopsticks eat () on the right hand side; signal (chopstick [(I + 1) % 5]); // release the chopsticks signal (chopstick [I]) On the right hand side; // release the left-hand chopsticks signal (room); // exit the room and release the semaphore room }}



B. Principle: The philosopher is allowed to pick up and eat chopsticks only when both of them are available.
Method 1: implemented using the AND semaphore mechanism: according to the course, in a primitive
Multiple critical resources are either allocated to them in full or not, so no deadlock occurs. When
When some resources are insufficient, the calling process is blocked. Because of the existence of the waiting queue, the requests to resources meet the requirements of FIFO,
Therefore, there will be no hunger.
Pseudo code:
semaphore chopstick[5]={1,1,1,1,1}; void philosopher(int I) { while(true) { think(); Swait(chopstick[(I+1)]%5,chopstick[I]); eat(); Ssignal(chopstick[(I+1)]%5,chopstick[I]); } } 

Method 2: Use the semaphore protection mechanism. Use the semaphores mutex to take the chopsticks on the left and right before eat ().
Sub-actions are protected to make them an atomic operation, which can prevent deadlocks.
Pseudo code:
semaphore mutex = 1 ; semaphore chopstick[5]={1,1,1,1,1}; void philosopher(int I) { while(true) { think(); wait(mutex); wait(chopstick[(I+1)]%5); wait(chopstick[I]); signal(mutex); eat(); signal(chopstick[(I+1)]%5); signal(chopstick[I]); } } 

C. Principle: it is required that philosophers of the odd number first pick up the chopsticks on his left and then take the chopsticks on his right.
Philosophers are the opposite. According to this rule, philosophers 1 and 3 compete for Chopsticks 1, and philosophers 3 and 3 compete for chopsticks 3.
Each of the five philosophers competed for an odd number of chopsticks. After obtaining them, they competed for an even number of chopsticks. In the end, there was always a philosopher who could obtain them.
Eat with two chopsticks. However, philosophers who cannot be applied enter the blocking wait queue, and follow the FIFO principle.
Scientists will be able to eat first, so there will be no philosophers who starve to death.
Pseudo code:
Semaphore chopstick [5] = {1, 1, 1}; void philosopher (int I) {while (true) {think (); if (I % 2 = 0) // even philosophers, right first and left. {Wait (chopstick [I + 1] mod 5); wait (chopstick [I]); eat (); signal (chopstick [I + 1] mod 5 ); signal (chopstick [I]);} Else // an odd number of philosophers, first left and right. {Wait (chopstick [I]); wait (chopstick [I + 1] mod 5); eat (); signal (chopstick [I]); signal (chopstick [I + 1] mod 5 );}}}

D. Implement through the management mechanism (the implementation fails in the end, as shown in the following analysis ):
Principle: Set a semaphore for each philosopher instead of for each chopsticks. The test () function provides the following functions:
Usage:
A. If the philosophers currently dealing with are in hunger and the philosophers on both sides are not in the eating state
The test () function tries to enter the eating state.
B. If it fails to enter the eating state through test (), the current philosopher will block and wait in the semaphore
Other philosophers use test () to set the philosopher's state to EATING.
C. When a philosopher process calls put_forks () to put down chopsticks, it will test its neighbor through test,
If the neighbor is in hunger and the neighbor is not in the eating state, the neighbor enters the eating state.
As mentioned above, this algorithm will not experience deadlocks, because a philosopher can accept this algorithm only when neither of the two adjacent seats is at dinner.
May be converted to the meal status.
This algorithm will result in a situation where a philosopher cannot eat at the end, that is, when the philosophers alternate between the left and right philosophers
When eating, the philosopher is always unable to enter the eating state, so it does not meet the requirements of the questions.
However, this algorithm can achieve the maximum degree of parallelism for any number of philosophers.
.
Pseudo code:
# Define N 5/* Number of philosophers */# define LEFT (I-1 + N) % N/* I LEFT Neighbor number */# define RIGHT (I + 1) % N/* I's right Neighbor number */typedef enum {THINKING, HUNGRY, EATING} phil_state; /* philosopher state */monitor dp/* manager */{phil_state state [N]; semaphore mutex = 1; semaphore s [N];/* Each philosopher has a semaphore, the initial value is 0 */void test (int I) {if (state [I] = HUNGRY & state [LEFT (I)]! = EATING & state [RIGHT (I)]! = EATING) {state [I] = EATING; V (s [I]) ;}} void get_forks (int I) {P (mutex); state [I] = HUNGRY; test (I);/* try to get two chopsticks */V (mutex); P (s [I]); /* If the chopsticks are not obtained, blocking */} void put_forks (int I) {P (mutex); state [I] = THINKING; test (LEFT (I )); /* check whether the left neighbor has a meal */test (RIGHT (I);/* check whether the RIGHT neighbor has a meal */V (mutex );}}

The philosophers process is as follows:
void philosopher(int process){ while(true) { think(); get_forks(process); eat(); put_forks(process); } } 

After reading the above, I am a little dizzy. I am familiar with a few questions.

[Example 1]Producer-consumer problems
In a multi-program environment, process synchronization is a very important and interesting issue, and the producer-consumer issue is a representative process synchronization problem. The following describes the producer-consumer problem in various situations. In-depth analysis and thorough understanding of this example will be of great help to solve the synchronization and mutex problems in the operating system.

(1) A producer, a consumer, and a buffer zone.
Define two synchronous semaphores:
Empty -- indicates whether the buffer is empty. The initial value is 1.
Full -- indicates whether the buffer is full and the initial value is 0.
Producer Process
While (TRUE ){
Produce a product;
P (empty );
The product is sent to Buffer;
V (full );
}
Consumer Process
While (True ){
P (full );
Extracts a product from the Buffer;
V (empty );
Consume this product;
}
(2) A producer and a consumer share n circular buffers.
Define two synchronous semaphores:
Empty -- indicates whether the buffer is null and the initial value is n.
Full -- indicates whether the buffer is full and the initial value is 0.

Set the buffer number to 1 ~ N-1 defines two pointers, in and out, which are used by the producer process and the consumer process respectively.
, Pointing to the next available buffer.
Producer Process
While (TRUE ){
Produce a product;
P (empty );
The product is sent to buffer (in );
In = (in + 1) mod n;
V (full );
}

Consumer Process
While (TRUE ){
P (full );
Extracts the product from buffer (out;
Out = (out + 1) mod n;
V (empty );
Consume this product;
}
(3) A group of producers and consumers share n circular buffers.
In this case, not only do producers and consumers need to be synchronized, but also each producer and consumer must access the buffer mutually.
Define four semaphores:
Empty -- indicates whether the buffer is null and the initial value is n.
Full -- indicates whether the buffer is full and the initial value is 0.
Mutex1: mutex semaphores between producers. The initial value is 1.
Mutex2: mutex semaphores between consumers. The initial value is 1.

Set the buffer number to 1 ~ N-1 defines two pointers, in and out, which are the pointers used by the producer process and consumer process, pointing to the next available buffer.
Producer Process
While (TRUE ){
Produce a product;
P (empty );
P (mutex1 );
The product is sent to buffer (in );
In = (in + 1) mod n;
V (mutex1 );
V (full );
}
Consumer Process
While (TRUE ){
P (full)
P (mutex2 );
Extracts the product from buffer (out;
Out = (out + 1) mod n;
V (mutex2 );
V (empty );
Consume this product;
}
Note that the order of two P operations cannot be reversed in both the producer process and the consumer process. Execute the P operation for synchronizing semaphores first, and then execute the P operation for mutex semaphores. Otherwise, the process may be deadlocked.

[Example 2]There is an empty disk on the table that can store a fruit. Dad can put an apple in the disk, or an orange in the disk, and his son can eat the oranges in the disk, and his daughter can eat the apples in the disk. When the disk is empty, only one fruit can be put at a time for users to use. Use the P and V primitives to synchronize the three concurrent processes, Father, Son, and daughter.

AnalysisIn this question, Dad, son, and daughter share one plate and can only put one fruit at a time. When the plate is empty, Dad can put a fruit into the fruit tray. If the fruit is an orange, the son is allowed to eat, and the daughter must wait. If the fruit is an apple, the daughter is allowed to eat, and the son must wait. This question is actually a variant of the producer-consumer issue. There are two types of products that the producer puts into the buffer, and two types of consumers. Each type of consumer consumes only one fixed type of products.

Solution: In this question, we should set three semaphores S, So, and Sa. semaphores S indicate whether the plate is empty, and their initial values are l. semaphores So indicate whether there are oranges in the disk, the initial value is 0; the semaphore Sa indicates whether an apple exists in the disk. The initial value is 0. Synchronization is described as follows:
Int S = 1;
Int Sa = 0;
Int So = 0;
Main ()
{
Cobegin
Father ();/* parent process */
Son ();/* son process */
Daughter ();/* daughter process */
Coend
}
Father ()
{
While (1)
{
P (S );
Put the fruit into the dish;
If (in orange) V (So );
Else V (Sa );
}
}
Son ()
{
While (1)
{
P (So );
Retrieve oranges from the tray;
V (S );
Eat oranges;
}
}
Daughter ()
{
While (1)
{
P (Sa );
Remove the apple from the drive;
V (S );
Eat apple;
}
}

Questions:

Four processes A, B, C, and D must read A shared file F. The system allows multiple processes to read the file F at the same time. But the restriction is that process A and process C cannot read the file F at the same time, and process B and process D cannot read the file F at the same time. To allow the four processes to use files as required by the System During Concurrent execution, the PV operation is used for management. Please answer the following questions:
(1) semaphores and initial values to be defined :.
(2) Fill in appropriate P and V Operations in the following programs to ensure that they can work correctly concurrently:
A () B () C () D ()
{{{{
[1]; [3]; [5]; [7];
Read F;
[2]; [4]; [6]; [8];
}}}}

Answers to questions:
(1) define two semaphores S1 and S2. The initial values are 1, that is, S1 = 1, S2 = 1. Process A and C use semaphores S1, and process B and D use semaphores S2.
(2) From [1] to [8]: P (S1) V (S1) P (S2) V (S2) P (S1) V (S1) P (S2) V (S2)

1. The data collection task in the measurement control system sends the collected data to a single buffer zone. The computing task extracts the data from the buffer zone for calculation. Try to write out a synchronization algorithm that uses the semaphore mechanism to share the single buffer between the two.

Var Sempty, Sfull: semaphore: = 1, 0

Begin

Parbegin

Collection: begin

Repeat

Collect a data;

Wait (Sempty );

Put data into the buffer;

Signal (Sfull );

Untill false;

End;

Compute: begin

Repeat

Wait (Sfull );

Extracts data from the buffer zone;

Signal (Sempty );

Computing;

'Until false;

End;

Parend

End

2. There is a reading room with 100 seats in total. When entering the table, the reader must first register on a registration form, which is a table listing each seat, including the seat number and the reader name. When the reader leaves, the registration content should be deregistered. Use the wait and signal primitives to describe reader process synchronization issues.

Var mutex, readcount: semaphore: = 1,100;

Begin

Parbegin

Process Reader: begin

Repeat

Wait (readcount );

Wait (mutex );

<Fill in the landline number and name to complete registration>;

Signal (mutex );

<Read>

Wait (mutex)

<Delete related table items in the registration form and complete cancellation>

Signal (mutex );

Signal (readcount );

Until false;

End;

Parend;

End;

1) there is a blank disk on the table. Only one fruit is allowed. Dad puts apples in the disk and his mother puts oranges in the disk. Her daughter eats apples in the disk and her son eats oranges in the disk; use the wait and signal primitives to synchronize data between fathers, mothers, daughters, and sons.

Var Sempty, Sapple, Sorange,: semaphore: =, 0, 0;

Begin

Parbegin

Father: begin

Repeat

Wait (Sempty); <put apple in tray>;

Signal (Sapple); until false;

End;

Mother: begin

Repeat

Wait (Sempty); <put orange in tray>;

Signal (Sorange); until false;

End;

Son: begin

Repeat

Wait (Sorange );

<Take orange>;

Signal (Sempty );

Until false;

End;

Daughter: begin

Repeat

Wait (Sapple );

<Take apple>;

Signal (Sempty); until false;

End;

Parend;

End;

1. In the 4*100-meter race, the four athletes had the following relationship: athlete 1 ran to the end and handed the baton to athlete 2; athlete 2 was in the waiting state at the beginning, the runner can only run forward after receiving a baton from athlete 1. After running 100 meters, the runner is handed over to athlete 3. The runner 3 can only run after receiving a baton from athlete 2, after running 100 meters, he handed it over to athlete 4. Then, when the Player 4 received the rod, he ran the whole process. Use the semaphore mechanism to analyze the above process.

Var s1, s2, s3: semaphpre: = 0, 0;

Begin

Parbegin

Athlete1: begin

Run100m;

Signal (s1 );

End;

Athlete2: begin

Wait (s1 );

Run100m;

Signal (s2 );

End;

Athlete3: begin

Wait (s2 );

Run100m;

Signal (s3 );

End;

Athlete4: begin

Wait (s3 );

Run100m;

End;

Parend;

End

2. on a bus, the driver and the conductor work for each other. The driver is responsible for driving and parking on the bus. The conductor is responsible for selling tickets and opening and closing the doors. When the conductor closes the doors, the driver can drive. Use the wait and signal operations to synchronize drivers with the conductor.

Var s1, s2: semaphore: = 0, 0;

Begin

Parbegin

Process Driver

Begin

Repeat

<Go right>;

<Stop bus>;

Signal (s2 );

Wait (s1 );

Until false;

End;

Process BookingClerk;

Begin

Repeat

<Ticketing>;

Wait (s2 );

<Open the door>;

<Close the door>;

Signal (s1 );

Until false

End;

Parend;

End;

1. Assume there are three concurrent processes: P, Q, and R. P reads information from the input device and sends it to Q. Q processes the information and sends it to R, R is responsible for printing the output. Process p and Q share a buffer pool consisting of m buffers; process Q and R share a buffer pool composed of n buffers (assuming the buffer pool is large enough, the unit of information transmitted between processes is smaller than or equal to the buffer length). Write a concurrent program that meets the preceding conditions. (12 points)

Var mutex1, mutex2, Sip, Siq, Soq, Sor: semaphore: = 1, 1, m, 0, n, 0;

Begin

Parbegin

Process P

Begin

Repeat

<Read information>

Wait (Sip );

Wait (mutex1 );

<Data into the buffer zone>

Signal (mutex1 );

Signal (Siq );

Until false

End;

Process Q

Begin

Repeat

Wait (Siq );

Wait (mutex1 );

<Retrieve data from the buffer zone>

Signal (mutex1 );

Signal (Sip );

<Data Processing> 〉

Wait (Soq );

Wait (mutex2 );

<Put processed data into the buffer zone>

Signal (mutex2 );

Signal (Sor );

Until false

End;

Process R

Repeat

Wait (Sor );

Wait (mutex2 );

<Send data to the printer for printing>;

Signal (mutex2 );

Signal (Soq );

Until false

End

Parend

End

2. There is an iron cage. Only one animal can be put at a time. hunters put tigers in the cage, and farmers put pigs in the cage. The zoo is waiting for the tigers in the cage, the hotel is waiting for pig in the cage. Use the wait and signal operations to write programs that can be synchronized.

Var Sempty, Stiger, Spig,: semaphore: =, 0, 0;

Begin

Parbegin

Hunter: begin

Repeat

Wait (Sempty );

<Put tiger in cage>;

Signal (Stiger );

Until false;

End;

Farmer: begin

Repeat

Wait (Sempty );

<Put pig in cage>;

Signal (Spig );

Until false;

End;

Zoo: begin

Repeat

Wait (Stiger );

<Take tiger>;

Signal (Sempty );

Until false;

End;

Hotel: begin

Repeat

Wait (Spig );

<Take pig>;

Signal (Sempty); until false;

End;

Parend;

End;

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.