介绍
#include <pthread.h>
pthread_cond_t cond;
int pthread_cond_init(pthread_cond_t *restrict cond,
const pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);
功能:初始化/销毁条件变量
参数:
- cond:条件变量的地址
- attr:条件变量属性,一般使用默认属性,指定为 NULL
返回值:
- 成功返回 0
- 失败返回错误号
#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex);
功能:阻塞调用该函数的线程
- pthread_cond_wait 在阻塞线程中,如果已经对互斥锁上锁,为避免死锁会把锁打开
- 当线程解除阻塞的时候,函数内部会帮助这个线程再次将互斥锁锁上,继续向下访问临界区
参数:
- cond:条件变量的地址
- mutex:互斥锁的地址
返回值:
- 成功返回 0
- 失败返回错误号
#include <pthread.h>
int pthread_cond_signal(pthread_cond_t *cond); // 唤醒至少一个
int pthread_cond_broadcast(pthread_cond_t *cond); // 唤醒所有
功能:唤醒阻塞在条件变量上的线程
参数:
- cond:条件变量的地址
返回值:
- 成功返回 0
- 失败返回错误号
简单使用
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#define N 30
pthread_mutex_t mutex;
pthread_cond_t empty, full;
int buf[N], idx = -1;
void * producer(void *arg)
{
while (1) {
pthread_mutex_lock(&mutex);
while (idx == N - 1) {
pthread_cond_wait(&empty, &mutex);
}
buf[++idx] = 1;
printf("producer offer %d\n", idx);
pthread_cond_signal(&full);
pthread_mutex_unlock(&mutex);
sleep(1);
}
pthread_exit(NULL);
}
void * consumer(void *arg)
{
while (1) {
pthread_mutex_lock(&mutex);
while (idx == -1) {
pthread_cond_wait(&full, &mutex);
}
printf("consumer get %d\n", idx);
buf[idx--] = 0;
pthread_cond_signal(&empty);
pthread_mutex_unlock(&mutex);
sleep(3);
}
pthread_exit(NULL);
}
int main()
{
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&empty, NULL);
pthread_cond_init(&full, NULL);
pthread_t t1[5], t2[5];
for (int i = 0; i < 5; i++) {
pthread_create(&t1[i], NULL, producer, NULL);
pthread_create(&t2[i], NULL, consumer, NULL);
}
for (int i = 0; i < 5; i++) {
pthread_join(t1[i], NULL);
pthread_join(t2[i], NULL);
}
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&empty);
pthread_cond_destroy(&full);
return 0;
}
注意事项
- pthread_cond_signal 要放在 unlock 之前
- 要使用两个条件变量。如果只使用一个且搭配 pthread_cond_signal(),会导致消费者线程唤醒消费者线程,导致生产者线程无限阻塞