生产者消费者模型优点
解耦
支持并发
支持忙闲不均
条件变量
当一个线程互斥地访问某个变量时,它可能发现在其它线程改变状态之前,它什么也做不了。
例如一个线程访问队列时,发现队列为空,它只能等待,只到其它线程将一个节点添加到队列中。这种情 况就需要用到条件变量。
条件变量可以用来定义变量或对象。
条件变量相关的接口
条件变量函数 初始化
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict
attr);
参数:
cond:要初始化的条件变量
attr:NULL
销毁
int pthread_cond_destroy(pthread_cond_t *cond)
等待条件满足
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
参数:
cond:要在这个条件变量上等待
mutex:互斥量,后面详细解释
pthread_cond_wait细节
//临界区:
//pthread_cond_wait 第二个参数必须为我们正在使用的互斥锁!!!
//1.pthread_cond_wait:该函数在调用的时候,会以原子性的方式将锁释放,并将自己挂起
//2.pthread_cond_wait:该函数在被唤醒返回的时候,会自动重新获取当时传入的锁
唤醒等待
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
将一个线程投入一个队列中,让其在某个条件变量下等待,自动排队时,可以让其他线程唤醒指定线程。
一次唤醒一个线程
//一次唤醒一个线程
pthread_cond_wait(&cond,&mutex);
一次唤醒批线程
//一次唤醒批线程
pthread_cond_broadcast(&cond,&mutex);
#include<iostream>
#include<cstdio>
#include<string>
#include<unistd.h>
#include<pthread.h>
using namespace std;
int tickets=1000;
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
void* start_routine(void* args)
{
string name =static_cast<const char*>(args);
while(true)
{
pthread_mutex_lock(&mutex);
//一次唤醒一个线程
//pthread_cond_wait(&cond,&mutex);
//一次唤醒批线程
pthread_cond_broadcast(&cond,&mutex);
cout<<name<<" -> "<<tickets<<endl;
tickets--;
pthread_mutex_unlock(&mutex);
}
}
int main()
{
//创建一批线程
pthread_t t[5];
for(int i=0;i<5;i++)
{
char* name =new char[64];
snprintf(name,64,"thread: %d",i+1);
pthread_create(t+i,nullptr,start_routine,name);
}
//通过条件变量控制线程执行
while(true)
{
sleep(1);
pthread_cond_signal(&cond);
cout<<"main thread wakeup one thread..."<<endl;
}
for(int i=0;i<5;i++)
{
pthread_join(t[i],nullptr);
}
return 0;
}
基于BlockingQueue的生产者消费者模型
#pragma once
#include<iostream>
#include<queue>
#include<pthread.h>
#include<unistd.h>
using namespace std;
static const int gmaxcap=5;
template<class T>
class BlockQueue
{
public:
BlockQueue(const int& maxcap=gmaxcap)
:_maxcap(maxcap)
{
pthread_mutex_init(&_mutex,nullptr);
pthread_cond_init(&_pcond,nullptr);
pthread_cond_init(&_ccond,nullptr);
}
void push(const T& in)//输入型参数,const &
{
pthread_mutex_lock(&_mutex);
//1.判断
while(is_full())//防止向队列中多push内容->提高代码健壮性
{//生产条件不满足无法生产,需要生产者等待
//临界区:
//pthread_cond_wait 第二个参数必须为我们正在使用的互斥锁!!!
//1.pthread_cond_wait:该函数在调用的时候,会以原子性的方式将锁释放,并将自己挂起
//2.pthread_cond_wait:该函数在被唤醒返回的时候,会自动重新获取当时传入的锁
pthread_cond_wait(&_pcond,&_mutex);
}
_q.push(in);
//pthread_cond_signal即可在临界区内也可在临界区外
pthread_cond_signal(&_ccond);
pthread_mutex_unlock(&_mutex);
}
void pop(T* out)//输出型参数:*, // 输入输出型:&
{
pthread_mutex_lock(&_mutex);
if(is_empty())
{
pthread_cond_wait(&_ccond,&_mutex);
}
*out=_q.front();
_q.pop();
pthread_cond_signal(&_pcond);
pthread_mutex_unlock(&_mutex);
}
~BlockQueue()
{
pthread_mutex_destroy(&_mutex);
pthread_cond_destroy(&_pcond);
pthread_cond_destroy(&_ccond);
}
private:
bool is_empty()
{
return _q.empty();
}
bool is_full()
{
return _q.size()==_maxcap;
}
queue<T> _q;
int _maxcap;//队列中元素的上限
pthread_mutex_t _mutex;
pthread_cond_t _pcond;//生产者对应的条件变量
pthread_cond_t _ccond;//消费者对应的条件变量
};
往阻塞队列中放内容:
#include"BlockQueue.hpp"
#include<time.h>
#include<sys/types.h>
void *consumer(void* bq_)
{
BlockQueue<int>* bq=static_cast<BlockQueue<int>*>(bq_);
while(true)
{
//消费活动
int data;
bq->pop(&data);
cout<<"消费数据: "<<data<<endl;
sleep(1);
}
return nullptr;
}
void* productor(void *bq_)
{
BlockQueue<int>* bq=static_cast<BlockQueue<int>*>(bq_);
while(true)
{
//生产活动-x先用随机数构建数据
int data=rand()%10+1;
bq->push(data);
cout<<"生产数据: "<<data<<endl;
sleep(1);
}
return nullptr;
}
int main()
{
srand((unsigned long)time(nullptr));
BlockQueue<int>* bq=new BlockQueue<int>();
pthread_t c,p;
pthread_create(&c,nullptr,consumer,bq);
pthread_create(&p,nullptr,productor,bq);
pthread_join(c,nullptr);
pthread_join(p,nullptr);
delete bq;
return 0;
}
BlockQueue<int>* bq=new BlockQueue<int>();
优化:int有点low可以将int换为其他。
生产数据: 10
消费数据: 10
生产数据: 1
消费数据: 1
生产数据: 1
消费数据: 1
生产数据: 3
消费数据: 3
生产数据: 7
消费数据: 7
sleep函数的头文件
sleep函数的头文件_sleep函数头文件-CSDN博客https://blog.csdn.net/modi000/article/details/117064651