条件变量原理
条件变量的工作原理
- 条件变量是一种相对复杂的线程同步方法
- 允许线程在一定条件没有满足的时候睡眠,知道满足某种条件的时候唤醒线程
- 当满足条件的时候,向线程发出信号唤醒
线程同步的生产者消费者模型其实是存在漏洞的,比如当仓库满的时候,生产者此时应该停止生产,同样的,当仓库为0的时候,消费者也应该是待消费状态。
缓冲区为0,消费者必须等待,缓冲区满,生产者必须等待。
当缓冲区为0,生产者生产了一个产品,此时要唤醒在等待的消费者。同理,当缓冲区满,消费者消费一件商品,生产者此时应该被唤醒。
操作系统提供的C语言API
条件变量配合互斥量使用
定义 pthread_cond_t
等待条件满足 pthread_cond_wait
等待被唤醒 pthread_cond_signal
实现生产者消费者模型
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <queue>
#include <unistd.h>
#include <pthread.h>
int MAX_BUF = 20;
int num = 0;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* producer(void*){
while(true){
pthread_mutex_lock(&mutex);
while (num >= MAX_BUF){
// 等待
printf("缓冲区满了, 等待消费者消费...\n");
pthread_cond_wait(&cond, &mutex);
}
num += 1;
printf("生产一个产品,当前产品数量为:%d\n", num);
sleep(1); // 生产产品需要的时间
pthread_cond_signal(&cond);
printf("通知消费者...\n");
pthread_mutex_unlock(&mutex);
sleep(1); // 生产产品的频率
}
}
void* consumer(void*){
while(true){
pthread_mutex_lock(&mutex);
while (num <= 0){
// 等待
printf("缓冲区空了, 等待生产者生产...\n");
pthread_cond_wait(&cond, &mutex);
}
num -= 1;
printf("消费一个产品,当前产品数量为:%d\n", num);
sleep(1);
pthread_cond_signal(&cond);
printf("通知生产者...\n");
pthread_mutex_unlock(&mutex);
}
}
int main(){
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, &consumer, NULL);
pthread_create(&thread2, NULL, &producer, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return 0;
}
运行结果是一个不断执行的进程,轮流打印仓库数量
缓冲区空了, 等待生产者生产...
生产一个产品,当前产品数量为:1
通知消费者...
消费一个产品,当前产品数量为:0
通知生产者...
缓冲区空了, 等待生产者生产...
生产一个产品,当前产品数量为:1
通知消费者...
消费一个产品,当前产品数量为:0
通知生产者...
缓冲区空了, 等待生产者生产...
生产一个产品,当前产品数量为:1
通知消费者...
消费一个产品,当前产品数量为:0
通知生产者...
...................
通过上述代码的通知与等待严格意义上实现了一个生产者与消费者模型。