The main content of this article:
- The realization of signal volume
- Using semaphores to solve the problem of philosophers ' dining
- Using semaphores to solve producer consumer problems
first, the realization of the signal volume1.1 semaphore Structure
struct { int value; struct process * list} semaphore;
Value represents the number of current semaphores that can be used, and the list represents the process waiting on the current semaphore.
1.2 p Operation implementation
P (semaphore * s) { s.value--; if 0 { Add current process to s.list; Block (); }}
If s.value<0. Indicates that no resources are available, the current process joins the list (waiting for a process listing), and the block current process.
1.3 v Operation implementation
V (semaphore * s) { S.value++ ; if 0 ) { from s.list; Wakeup (A); }}
s++ represents the release of a resource if s.value++ is still <=0. Indicates that at least one process is waiting for a resource, this time take a few processes from the list, wakeup the process, so that the process can begin to use the resources that have just been released (this process does not necessarily start running immediately, at least the ready state, When to run depends on the CPU's scheduling algorithm).
1.4 Busy Wait issues
The previous Peterson scheme was to achieve mutually exclusive access between processes by busy waiting. PV operation is also unavoidable, the premise of PV operation is that there will be no two processes for a semaphore at the same time the PV operation. This time the semaphore is the semaphore is the critical region, how to let P and V operation for the operation of the signal is mutually exclusive?
The operating system is also done for this by a busy wait (when a process operates on the semaphore, other processes wait). However, the busy wait is finally prevented at the semaphore level to minimize the amount of busy waiting time, because the PV operation time is very fast.
Ii. using semaphores to solve the problem of philosophers ' dining2.1 Problem Demo
Five philosophers, as shown:
- Each of the two philosophers has a chopstick, a total of 5
- Philosophers are thinking, when they are hungry, they pick up their chopsticks to eat.
- Only after taking two chopsticks can we start eating.
Obviously, if a philosopher wants to eat, if any of his neighbours are eating, he is not able to eat, chopsticks are not enough (either only one chopstick or none).
2.2 Solutions
void philosopher (i) { while (true) { P (chopstick[i]); 1 5 ]); Eat (); V (Chopstick[i]); 1 5 ]); Think (); }}
I represent the first philosopher (0,1,2,3,4,5). The core idea of the program is to use the PV operation to let philosophers wait until their left and right chopsticks are free to start eating, then put the chopsticks back after eating.
Number of philosophers and chopsticks
When the philosopher 0 wanted to dine, waiting for 0,1 chopsticks, philosopher 2 wanted to dine while waiting for 2,3 chopsticks.
2.3 Questions
The above scenario has one drawback:
When all philosophers want to eat at the same time, a deadlock will occur, waiting forever (starvation):
The next blog post specifically describes how to solve starvation.
Third, the use of signal volume to solve the problem of producer consumers
The previous article introduced the producer and consumer model, but there is a problem with the pattern, wakeup may be lost, in fact, the core problem is because access to count (buffer capacity) does not make process mutex access, access to buffer is not mutually exclusive access, This problem can be solved by PV operation
Set three semaphores:
- Full, which represents the number of item in buffer, defaults to 0
- Empty represents the amount of free in buffer, and the default is the capacity of buffer n
- Mutex, which provides a mutex operation for buffer, and 1 delegates can access buffer. 0 means no access to buffer, with an initial value of 1;
void producer () { while(true) { produce_item (); P (empty);//idle Capacity-1, no idle capacity, then wait, and enter the Block list P (mutex);//detects if buffer can access insert_item (); V (mutex);//release buffer access V (full),//item number +1, if there is consumer wait, wake up a consumer }}void Consumer () { while(true) { P (full);//item number-1, if no item can be consumed, Enter the Block list P (mutex);//detects if buffer can access remove_item (); V (mutex);//release buffer access V (empty);//idle capacity +1, if there is producer wait, then wake up a producer consume_item (); }}
Operating system-process/thread internal communication-semaphores, implementation and application of PV operations (to solve the problem of philosophers eating and producer consumers)