This is the 10th day of my participation in the More text Challenge. For more details, see more text Challenge

Producer consumer problem (a classic example for understanding mutual exclusion and synchronization between threads)


Mutually exclusive: For a critical resource area, only one thread can access it at a time. Equivalent to the warehouse, the production of good products into the warehouse, can not take things from the warehouse; When you take things from the warehouse, you can’t put the finished product into the warehouse. Interprocess synchronization: Some threads need to run in order, so interprocess synchronization is used. It is equivalent to the warehouse. Only when the number of products in the warehouse is greater than 0, the operation of taking products from the warehouse can be carried out. Only when the number of products in the warehouse is less than the total, the operation of new products can be carried out.

Interthread exclusion: mutex interthread synchronization: semaphore

/************************************************************************* > File Name: pv.c > Author: LiYongjun > Mail: [email protected] > Created Time: Mon 25 Feb 2019 02:10:47 PM CST ************************************************************************/ #include <stdio.h> #include <unistd.h> #include <pthread.h> #include <semaphore.h> pthread_mutex_t mutex; // Sem_t empty, full; // Sem_t empty, full; // semaphore for synchronization, producer consumer problem int sum; void *t1_fun(void *arg) { while(1) { sem_wait(&full); //full - 1 pthread_mutex_lock(&mutex); / / lock sum -; printf("thread 1, sum = %d\n", sum); sleep(1); pthread_mutex_unlock(&mutex); / / unlock sem_post (& empty); //wait + 1 } } void *t2_fun(void *arg) { while(1) { sem_wait(&empty); //empty - 1 pthread_mutex_lock(&mutex); / / lock sum++; printf("thread 2, sum = %d\n", sum); sleep(3); pthread_mutex_unlock(&mutex); / / unlock sem_post (& full); //full + 1 } } int main(int argc, char *argv[]) { pthread_mutex_init(&mutex, NULL); // Initialize the mutex sem_init(&empty, 0, 5); // Initialize semaphore sem_init(&full, 0, 0); pthread_t t1, t2; pthread_create(&t1, NULL, t1_fun, NULL); pthread_create(&t2, NULL, t2_fun, NULL); while(1) { sleep(10); }}Copy the code

The execution result

[root@VM_0_14_centos test]# gcc pv.c -lpthread
[root@VM_0_14_centos test]# ./a.out 
thread 2, sum = 1
thread 2, sum = 2
thread 2, sum = 3
thread 2, sum = 4
thread 2, sum = 5
thread 1, sum = 4
thread 1, sum = 3
thread 1, sum = 2
thread 1, sum = 1
thread 1, sum = 0
thread 2, sum = 1
thread 2, sum = 2
thread 2, sum = 3
thread 2, sum = 4
thread 2, sum = 5

Copy the code

As you can see, the number of products in the warehouse is always between 0 and 5 (5 being the maximum capacity of the warehouse).

Pthread_mutex_init () ¶ int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr); The pthread_mutex_init() function creates the mutex dynamically, with the attr argument specifying the properties of the new mutex. If the attr argument is empty, the default mutex property is used, which is fast mutex.

Pthread_mutex_lock () When pthread_mutex_lock() returns, the mutex is locked. This function is called by a thread to lock the mutex, and if the mutex is already locked and owned by another thread, the calling thread blocks until the mutex becomes available.

Pthread_mutex_unlock () Pthread_mutex_unlock () frees the mutex referenced by the mutex.

Sem_init () : int sem_init(sem_t *sem, int pshared, unsigned int value); Sem: points to the semaphore object. Pshared: indicates the type of semaphore. If the value is not 0, the semaphore is shared between processes, otherwise it can only be shared by all threads of the current process. Value: specifies the value of the signal quantity

Sem_wait () Sem_wait is a function, also an atomic operation, that subtracts a “1” from the value of the semaphore, but it always waits for the semaphore to be nonzero before subtracting. That is, if you call sem_wait() on a semaphore with a value of 2, the thread will proceed, reducing the semaphore to 1. If you call sem_wait() on a semaphore with a value of zero, the function waits until another thread increments the value so that it is no longer zero.

Sem_post () Sem_POST adds a “1” to the value of the semaphore. It is an “atomic operation” — two threads that add a “1” to the same semaphore at the same time do not collide; Two programs that read and write the same file at the same time may collide.