目录
条件变量的相关接口:
- int pthread_cond_destroy(pthread_cond_t *cond);
- int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
- pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);//线程等待,线程首先参与锁的竞争,得到锁后才会返回
- int pthread_cond_broadcast(pthread_cond_t *cond);//唤醒多个线程
- int pthread_cond_signal(pthread_cond_t *cond);//唤醒一个线程
条件变量理解:
- 上图中两个人同时都需要共享资源中的数据,但资源是有限的,男孩拿了资源,那么女孩需要等资源存在再进行拿去,为了避免女孩白跑,三者之间存在一个消息,通知资源是否已到位,而这个消息就是条件变量。
生产消费模型:
以现实生活中的工厂举例:
- 工厂生产大批的商品运往各大超市,便利店等地方
- 消费者从超市、便利店等地方购买所需要的物品,而不是从供应商中拿去
- 超市就是工厂与消费者二者之间的一个传递关系
锁和条件变量即可实现以上三种关系
理解生产者消费者模型特点:
- 一个交易场所
- 两种角色(生产线程,消费线程)
- 三种关系
- 生产&&生产
- 消费&&消费
- 生产&&消费
消费者&&生产者接口:
生产者:
消费者:
伪唤醒:
情况:一个生产者只生产唯一的产品,但消费者有两位。
- 生产者生产完后,通知消费者消费,一次性唤醒多个线程
- 但产品是唯一的
- 多个线程同时唤醒时,都会参与锁的竞争
- 一个线程拿取到锁,wait返回,但其他线程开始在锁的位置等待
- 等上一个线程释放完锁后,直接拿取锁,不会走判断队列是否为空的代码。
- 线程进入空队列后,代码就出现了问题
总结:伪唤醒就是添加未被满足,但线程被异常唤醒叫做伪唤醒
生产消费模型内部封装:
const static int defaultcap=3;
template <typename T>
class Blockqueue
{
private:
bool Isfull()
{
return _block_queue.size()==_max_cap;
}
bool IsEmpty()
{
return _block_queue.empty();
}
public:
Blockqueue(int cap=defaultcap):_max_cap(cap)
{
pthread_mutex_init(&_mutex,nullptr);
pthread_cond_init(&_p_cond,nullptr);
pthread_cond_init(&_c_cond,nullptr);
}
void Pop(T *out)
{
pthread_mutex_lock(&_mutex);
while(IsEmpty())
{
pthread_cond_wait(&_c_cond,&_mutex);
}
*out=_block_queue.front();
_block_queue.pop();
pthread_mutex_unlock(&_mutex);
pthread_cond_signal(&_p_cond);//唤醒生产者生产
}
void enqueue(const T&in)
{
pthread_mutex_lock(&_mutex);
//判断队列是否满
while(Isfull())
{
//加锁后,线程判断队列是否已满
//队列满了,线程就会阻塞的等待
//等待的同时,该线程会释放锁
//当该函数返回之前,线程首先需要参与锁的竞争,重新加上锁
pthread_cond_wait(&_p_cond,&_mutex);
}
//没有满||队列为空,生产者生产
_block_queue.push(in);
pthread_mutex_unlock(&_mutex);
//对于线程的唤醒位置是否需要在释放锁的前后原因:
//1.放在释放锁的前面: 生产者唤醒消费者线程,消费者线程被唤醒
// 生产者释放锁,消费者竞争锁,拿取到锁,开始消费
//2.放在释放锁的后面: 生产者释放锁后同时又开始参与锁的竞争
// 唤醒消费线程,消费者线程参与锁的竞争
// 由于队列已满,生产者线程等待同时释放锁,消费者线程拿取到锁
pthread_cond_signal(&_c_cond);//唤醒消费者消费
}
~Blockqueue()
{
pthread_mutex_destroy(&_mutex);
pthread_cond_destroy(&_p_cond);
pthread_cond_destroy(&_c_cond);
}
private:
std::queue<T> _block_queue;
int _max_cap;
pthread_mutex_t _mutex;
//生产者
pthread_cond_t _p_cond;
//消费者
pthread_cond_t _c_cond;
};