Let's first look at the description of condition variables in Linux high performance server programming:
The above words can be summarized as follows:
Condition variables can be used when a thread in a multithread depends on the change of shared data by another thread!
It's easy to understand conditional variables with the of consumers and producers
As the elder brother mentioned above, it can be seen very thoroughly from the perspective of consumers and producers. Wake up when needed and sleep when not needed.
Let's take a look at the functions and header files used by conditional variables:
#include <pthread.h> // Header files are as like as two peas used for creating functions.
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *attr); // Initialization of condition variables
The first parameter is the pointer of the condition variable, and the second parameter is the attribute of the condition variable, which is generally set to NULL
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);// Wait until the condition variable is satisfied. After waking up, the thread will be started. Otherwise, the thread will always be blocked
The first parameter is a pointer to the condition variable, and the second parameter is a mutex (mutexes and condition variables are generally used together. Why? Because mutexes have only two states, locked and unlocked, while condition variables can send signals between threads to make threads wait or wake up, which makes up for the single locking mode of mutexes. Therefore, mutexes and condition variables are generally used together).
int pthread_cond_signal(pthread_cond_t *cond); // Wake up a single thread
int pthread_cond_broadcast(pthread_cond_t *cond); // Wake up all waiting threads
int pthread_cond_destroy(pthread_cond_t *cond); // Destruction of conditional variables
The parameters of the above three functions are pointers to conditional variables
Let's take a look at a piece of code. Its function is that the main thread writes data to the buff. In the process of writing, two sub threads are waiting. After the main thread writes, the sub thread completes printing. Then, when the main thread inputs end, the process ends!
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <pthread.h> pthread_mutex_t mutex; //Create mutex pthread_cond_t cond; //Create condition variable char buff[128] = {0}; void* funa(void* arg) { while( 1 ) { //Waiting conditions available pthread_mutex_lock(&mutex); pthread_cond_wait(&cond,&mutex); pthread_mutex_unlock(&mutex); if ( strncmp(buff,"end",3) == 0 ) { break; } //Print buff printf("funa buff=%s\n",buff); } } void * funb(void* arg) { while( 1 ) { //Waiting conditions available pthread_mutex_lock(&mutex); pthread_cond_wait(&cond,&mutex); //Wait for the signal from the main thread after locking the mutex pthread_mutex_unlock(&mutex); if ( strncmp(buff,"end",3) == 0 ) { break; } //Print buff printf("funb buff=%s\n",buff); } } int main() { pthread_cond_init(&cond,NULL); pthread_mutex_init(&mutex,NULL); pthread_t ida, idb; pthread_create(&ida,NULL,funa,NULL); pthread_create(&idb,NULL,funb,NULL); while( 1 ) { //Keyboard data acquisition - buff fgets(buff,128,stdin); //Notification thread signal broadcast if ( strncmp(buff,"end",3) == 0 ) { pthread_mutex_lock(&mutex); //Lock pthread_cond_broadcast(&cond); //When you enter end, wake up all threads and let everyone end together. Because threads are at the same level, the exit of the main thread does not affect the operation of child threads (mainly because there is a join function waiting for child threads below) pthread_mutex_unlock(&mutex); //Unlock break; } pthread_mutex_lock(&mutex); pthread_cond_signal(&cond); //Wake up one of the child threads pthread_mutex_unlock(&mutex); } pthread_join(ida,NULL); pthread_join(idb,NULL); pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond); exit(0); }
The two sub threads in the above code are the same. Let's look at the three lines of code in the sub thread:
How many locks are there?
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
pthread_mutex_unlock(&mutex);
How many locks are there in the above three lines of code? Think about it first
There are two locks. Let me stroke them for you. At the moment when the two sub threads function is created, the two sub threads compete for mutually exclusive locks. Only one thread can get the lock. The thread that does not get the lock will enter the blocking. Which thread gets the lock will be bound, and then go to the second line of the code mentioned above, pthread_cond_wait (&cond,&mutex) A mutex lock will be passed in the parameter. By the time of this line, the lock has actually been unlocked, and then it will wait for the signal from the main thread to wake up the thread. The same is true for another thread. At first, it did not get the lock, but after another sub thread is unlocked, the sub thread will wait for wake-up. At this time, the thread that did not get the lock at first will repeat the previous operation Work, and then enter the wait to wake up. However, when waking up, both sub threads are waiting. When waking up, one thread will wake up randomly. At this time, pthread_cond_wait (& cond, & mutex) When this line of code comes out, it will be shackled. Only one child thread can be awakened, and it will be awakened randomly! The thread that has not been awakened has been waiting for it