Condition variables are used to wait for threads, not locks, and are often used with mutex. Condition variables should be used with the mutex, mainly because of an obvious feature of the mutex is it has only two states: locking and non-locking, and condition variables can by allowing the thread block and wait for another thread to send signals to make up for the inadequacy of the mutex, so mutexes and condition variables are usually used together.

When the condition is met, the thread usually unlocks and waits for the condition to change. Once another thread modifies the environment variable, the corresponding environment variable is notified to wake up one or more threads blocked by the condition variable. These awakened threads are re-locked and the condition is tested. In general condition variables are used for synchronization between threads; One of the execution streams is allowed to suspend and wait when the condition is not met.

In short, condition variables are not locks themselves, but they can also cause threads to block, often in conjunction with mutex, providing a place for multiple threads to meet.

Advantages of conditional variables:

Compared to MUtex, conditional variables can reduce contention. If mutex is the only resource, producers and all consumers will rush to grab locks regardless of whether there is data in the shared resource, resulting in a waste of resources.

Using mutex directly, consumers need to compete for mutex as well as producers, but competing for mutex between consumers is meaningless if there is no data in the aggregation (linked list). With the conditional variable mechanism, only producers complete production, will cause competition between consumers. Improved program efficiency.

Main application functions:

Pthread_cond_init function Pthread_cond_destroy function Pthread_cond_wait function Pthread_cond_timedWait function Pthread_cond_signal function Pthread_cond_broadcast function

Each of the above six functions returns 0 on success or an error number on failure.

** Pthread_cond_t type: ** Used to define conditional variables, such as pthread_cond_t cond;

# # pthread_cond_init function

Function prototype:

int pthread_cond_init(pthread_cond_t

restrict cond, const pthread_condattr_t

restrict attr);

Function functions:

Initialize a condition variable

Parameter Description:

**cond: ** conditional variable that should be passed &cond to the function when called

**attr: ** Conditional variable attributes, usually passed NULL to indicate that the default attributes are used

Condition variables can also be initialized statically:

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

# # pthread_cond_destroy function

Function prototype:

int pthread_cond_destroy(pthread_cond_t *cond);

Function functions:

Destroys a condition variable

# # pthread_cond_wait function

Function prototype:

int pthread_cond_wait(pthread_cond_t

restrict cond, pthread_mutex_t

restrict mutex);

Function functions:

Block waiting for a condition variable. Specifically, it has the following three functions:

  1. Block until the condition variable cond (parameter 1) is satisfied;
  2. Releasing a mutex in hand is equivalent to pthread_mutex_unlock(&mutex);
  3. When awakened, the pthread_cond_wait function returns, unblocking and reapplying for the mutex

Among them, step 1 and step 2 are an atomic operation.

# # the function pthread_cond_timedwait

Function prototype:

int pthread_cond_timedwait(pthread_cond_t

restrict cond, pthread_mutex_t

restrict mutex, const struct timespec *restrict abstime);

Function functions:

Wait for a condition variable in time

Parameter Description:

The first two are easier to understand, with emphasis on the third parameter.

There is a struct timespec structure that can be viewed in man sem_timedWait. The prototype of the structure is as follows:

struct timespec {

​ time_t tv_sec; /

seconds

/ SEC.

​ long tv_nsec; /

nanosecondes

/ nanosecond

}

Struct timespec defines the parameter absTime as an absolute time. Notice, it’s absolute time, not relative time. What is absolute time? October 1, 2018, 10:10:00, that’s the absolute time. What is relative time? Set the washing machine for 30 minutes, which is a relative time, 30 minutes from the time of day, and so on.

For example, time(NULL) returns absolute time. Alarm (1) is the relative time, timed 1 second relative to the current time.

Adstime is relative to 00:00:00, January 1, 1970, the first year of UNIX timekeeping.

Struct timespec t = {1, 0}; struct timespec t = {1, 0}; pthread_cond_timedwait (&cond, &mutex, &t); This can only be timed to 00:00:01 seconds on January 1, 1970, presumably before anyone was born.

Correct usage: time_t cur = time(NULL); Gets the current time. struct timespec t; Define timespec struct variable t tv_sec = cur+1; Pthread_cond_timedwait (&cond, &mutex, &t); The ginseng

# # pthread_cond_signal function

Int pthread_cond_signal(pthread_cond_t *cond);

The wake () function wakes up at least one thread blocking on a condition variable

# # pthread_cond_broadcast function

Int pthread_cond_broadcast(pthread_cond_t *cond);

The wake () function wakes up all threads blocking on a condition variable

## Producer consumer condition variable model

Regardless of the language, when it comes to thread synchronization, a typical example is the producer-consumer model. In Linux, it is a common method to implement this model by means of condition variables.

Suppose you have two threads, one that simulates producer behavior and one that simulates consumer behavior. Two threads operate simultaneously on a shared resource (commonly called convergence), where production adds products and consumers consume products.

Consider the following example, using conditional variables to simulate producer/consumer problems:

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> typedef struct msg { struct msg *next; int num; }msg_t; msg_t *head = NULL; msg_t *mp = NULL; /* Statically initialize a condition variable and a mutex */ pthread_cond_t has_product = PTHREAD_COND_INITIALIZER; pthread_mutex_t mutex =PTHREAD_MUTEX_INITIALIZER; void *th_producer(void *arg) { while (1) { mp = malloc(sizeof(msg_t)); mp->num = rand() % 1000; Production of a product / / simulation printf (" -- -- -- produce: % d -- -- -- -- -- -- -- -- \ n ", mp - > num); pthread_mutex_lock(&mutex); mp->next = head; head = mp; pthread_mutex_unlock(&mutex); pthread_cond_signal(&has_product); // Wake up the thread to consume the product sleep(rand() % 5); } return NULL; } void *th_consumer(void *arg) { while (1) { pthread_mutex_lock(&mutex); Pthread_cond_wait (&has_product, &mutex); while (head == NULL) {pthread_cond_wait(&has_product, &mutex); } mp = head; head = mp->next; Pthread_mutex_unlock (&mutex); printf("========= consume: %d ======\n", mp->num); free(mp); mp = NULL; sleep(rand() % 5); } return NULL; } int main() { pthread_t pid, cid; srand(time(NULL)); pthread_create(&pid, NULL, th_producer, NULL); pthread_create(&cid, NULL, th_consumer, NULL); pthread_join(pid, NULL); pthread_join(cid, NULL); return 0; }Copy the code

Running results:

> < p style = “max-width: 100%; clear: both
#### read all is true love, a praise to walk again? Your “sanlian” is the biggest motivation for liang Xu’s continuous creation!
1\. Follow the ** original ** * public account “** Liangxu Linux**”, the first time to get the latest Linux dry goods!
2. Public account background reply [information] [interview] [resume] to get selected first-line big factory interview, self-improvement, resume and other information.
3\. Follow my blog: [lxlinux.net]([http://www.lxlinux.net]](http://www.lxlinux.net))