preface
The idea of solving the problem of synchronization and mutual exclusion comes from the summary notes of the explanation of kingcraft
Similar topics:
2014 real topic 47 is a variant of the classic producer consumer problem. You can refer to and learn the classic producer consumer problem first.
1, Train of thought
To solve the problem of synchronization and mutual exclusion, the ideas and steps are as follows:
1. Analyze the synchronous and mutually exclusive relationship between processes;
2. Set mutex = 1 and synchronization semaphore (generally, the number of available resources is empty = N).
3. It is best to draw a synchronous and mutually exclusive relationship diagram and judge which type it belongs to, such as producer consumer problem, reader writer problem, philosopher dining problem and smoker problem.
2, Title
45. There are multiple producer processes and consumer processes in the system, which share a ring buffer that can store 1000 products (initially empty). When the buffer is not full, the producer process can put a product it produces, otherwise it will wait; When the buffer is not empty, the consumer process can take a product, otherwise wait. A consumer process is required to continuously take out 10 products from the buffer before other consumer processes can take products. Please use semaphores P and V (wait, signed) to realize mutual exclusion and synchronization between processes. It is required to write a complete process; The meaning and initial value of the semaphore used are pointed out.
Solution: (1) mutually exclusive resources:
After a consumer process continuously takes out 10 products from the buffer, other consumer processes can take products. Set mutex1 = 1;
Producers and consumers set mutually exclusive semaphores for buffer access: mutex2 = 1;
(2) Synchronization relationship: if the producer and consumer processes share a buffer that can store 1000 products (initially empty), set the synchronization semaphore empty = 1000, representing several idle buffer units; Set the synchronization semaphore full = 0 to represent the number of products in the buffer at this time;
(3) The synchronization and mutual exclusion diagram is as follows: (producer consumer variant)
(4) The pseudo code is as follows:
Step 1: set semaphore
semaphore mutex1 = 1; semaphore mutex2 = 1; semaphore empty = 1000; // There are several free buffer units semaphore full = 0;
Step 2: first determine the producer consumer problem, and list the following pseudo code
producer(){ while(1){ Produce a product; Put the product into the buffer; } } consumer(){ while(1){ Remove a product from the buffer; Consume this product; } }
Step 3: set the process's single mutually exclusive access buffer
producer(){ while(1){ Produce a product; P(mutex2); Put the product into the buffer; V(mutex2); } } consumer(){ while(1){ P(mutex2); Remove a product from the buffer; V(mutex2); Consume this product; } }
Step 4: Producer: judge whether the buffer is empty before putting the product; Consumer: take out the product and then make room.
producer(){ while(1){ Produce a product; P(empty); // Determine whether the buffer is empty P(mutex2); Put the product into the buffer; V(mutex2); } } consumer(){ while(1){ P(mutex2); Remove a product from the buffer; V(mutex2); V(empty); // Take out the product and then make room Consume this product; } }
Step 5: after the producer produces a product, the number of products in the buffer zone is increased by one; After a consumer uses a product, the number of products in the buffer is reduced by one;
producer(){ while(1){ Produce a product; P(empty); // Determine whether the buffer is empty P(mutex2); Put the product into the buffer; V(mutex2); V(full); // Number of buffer products plus one } } consumer(){ while(1){ P(full); // Number of buffer products minus one P(mutex2); Remove a product from the buffer; V(mutex2); V(empty); // Take out the product and then make room Consume this product; } }
Step 6: different from the classic producer consumer problem, it requires one consumer process to continuously take 10 products from the buffer before other consumer processes can take products.
Therefore, the mutex signal mutex1 is used to realize the restriction between consumers, and the for loop is used to realize that a consumer can get products from the buffer only after 10 consecutive times.
producer(){ while(1){ Produce a product; P(empty); // Determine whether the buffer is empty P(mutex2); Put the product into the buffer; V(mutex2); V(full); // Number of buffer products plus one } } consumer(){ while(1){ P(mutex1); // Set the mutually exclusive semaphore to control the buffer within a cycle (10 times) of a consumer process for(int i = 0; i < 10; i++){ // Use the for loop to take 10 consecutive times P(full); // Number of buffer products minus one P(mutex2); Remove a product from the buffer; V(mutex2); V(empty); // Take out the product and then make room Consume this product; } V(mutex1); } }
The complete code is as follows:
semaphore mutex1 = 1; semaphore mutex2 = 1; semaphore empty = 1000; // There are several free buffer units semaphore full = 0; producer(){ while(1){ Produce a product; P(empty); // Determine whether the buffer is empty P(mutex2); Put the product into the buffer; V(mutex2); V(full); // Number of buffer products plus one } } consumer(){ while(1){ P(mutex1); // Set the mutually exclusive semaphore to control the buffer within a cycle (10 times) of a consumer process for(int i = 0; i < 10; i++){ // Use the for loop to take 10 consecutive times P(full); // Number of buffer products minus one P(mutex2); Remove a product from the buffer; V(mutex2); V(empty); // Take out the product and then make room Consume this product; } V(mutex1); } }
3, Further understanding
There are multiple producer processes and consumer processes in the system, which share a ring buffer that can store 1000 products (initially empty).
Ring buffer, equivalent to a circular queue. You can set a circular buffer with a size of 1000.
In this question, there is no need to judge whether the circular queue is "full / empty", because P(mutex) and P(full) are set to judge whether the buffer is empty and whether there are products in the buffer.
Note: judge whether the stack and queue are full/ Empty and its length.
full | empty | length | |
Stack | s->top == maxsize - 1; | s->top == -1; Sequence stack: S - > Top = = s - > base; | s->top + 1; |
queue | (Q.rear + 1) % maxsize == Q.front | Q.front == Q.rear == 0 Chain team: | (rear - front + maxsize) % maxsize |