条件变量
条件变量是用来等待线程而不是上锁的,条件变量通常和互斥锁一起使用,这因为互斥锁的一个明显的特点就是它只有两种状态:锁定和非锁定,而条件变量可以通过允许线程阻塞和等待另一个线程发送信号来弥补互斥锁的不足,所以互斥锁和条件变量通常一起使用。
一般条件变量有两个状态:
- 一个/多个线程为等待“条件变量的条件成立“而挂起(wait)
- 另一个线程在“条件变量条件成立时”通知其他线程(signal)
相关函数
操作 | 函数 |
---|---|
条件等待 | int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) |
计时等待 | int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) |
单个激活 | int pthread_cond_signal(pthread_cond_t *cond) |
全部激活 | int pthread_cond_broadcast(pthread_cond_t *cond) |
其中参数的意义:
- cond:条件变量
- mutex:互斥锁
- abstime:等待时间
返回值意义:单个激活和多个激活函数的返回值如果是0则表示成功,如果是正数则表示失败。超时等待返回ETIMEDOUT则表示超时结束等待。
实现场景
两个生产者拥有一个箱子,要求生产的目标产品必须放进箱子里,当生产的产品达到100个时,就用箱子将产品送至消费者处理,本博文中消费者的操作是对其进行输出。
代码详解
思路:
- 需要三个线程,分别模拟两个生产者和一个消费者
- 创建一个函数模拟生产者动作
- 当产品数目达到100个时通知消费者,消费者对其进行处理
- 当生产者线程生产的产品达到100个时,应对其进行阻塞,相应的唤醒消费者线程
这里需要特别注意的是生产数目达到预期值如何阻塞生产者同时唤醒消费者,因为有唤醒操作,所以我们需要使用条件变量,条件变量的wait的重要作用是,当该线程执行条件不满足(即产品数目是否达到100),若是不满足该函数就会让出互斥锁,阻塞当前线程。
具体代码如下:
#include <iostream>
#include <unistd.h>
#include <pthread.h>
using namespace std;
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; // 互斥锁
pthread_cond_t cv = PTHREAD_COND_INITIALIZER; // 信号
void* product(void* arg){
int& count = *static_cast<int*>(arg);
for