在日常生活中,当我们缺少生活用品时,我们会去超市购物,当我们买走超市货架上的东西,超市则会补充货架上的货物,那么超市的货物是从哪来的呢?不错,他们会有自己的供货商。那么我们是以怎样的身份进入超市呢?相信每个人都知道自己是以消费者的角色去的,生产者毫无疑问就是供货商,那么将我们与供货商这二者联系到一起的超市在这里面又扮演了什么样的角色呢?仔细想想便不难得出超市就是交易场所。
所以我们总结”321原则“来描述生产者消费者模型:
#include< semaphore.h>
int _sem_init(sem_t *sem,int pshared,unsigned int value)
参数:
pthread: 0表示线程间共享,非零表示进程间共享
value : 信号量初始值
int sem_destroy(sem_t *sem)
功能:等待信号量,会将信号量的值减1
int sem_wait(sem_t *sem);
功能:发布信号量,表示资源使用完毕,可以归还资源了。将信号量的值加1.
int sem_post(sem_t *sem);
//RingQueue.hpp
#pragma once
#include
#include
#include
#include
#define NUM 10
class RingQueue{
private:
std::vector<int> v;
int max_cap;
sem_t sem_blank; //生产者(空格子数)
sem_t sem_data; //消费者(数据数目)
int c_index;
int p_index;
private:
void P(sem_t &s)
{
sem_wait(&s);
}
void V(sem_t &s)
{
sem_post(&s);
}
public:
RingQueue(int _cap=NUM)
:max_cap(_cap)
,v(_cap),c_index(0),p_index(0)
{
sem_init(&sem_blank,0,max_cap);
sem_init(&sem_data,0,0);
}
void Get(int &out)
{
P(sem_data);
//消费
out=v[c_index];
c_index++;
c_index%=max_cap;
V(sem_blank);
}
void Put(const int &in)
{
P(sem_blank);
//生产
v[p_index++]=in;
p_index%=max_cap;
V(sem_data);
}
~RingQueue()
{
sem_destroy(&sem_blank);
sem_destroy(&sem_data);
c_index=0;
p_index=0;
}
};
// main.cc
#include"RingQueue.hpp"
void *consumer(void *ring_queue)
{
RingQueue *rq=(RingQueue*)ring_queue;
while(true){
int data=0;
rq->Get(data);
std::cout<<"consumer done...#"<<data<<std::endl;
}
}
void*productor(void*ring_queue)
{
RingQueue *rq=(RingQueue*)ring_queue;
int count=100;
while(true){
sleep(1);
rq->Put(count);
count++;
if(count>110)
count=100;
std::cout<<"productor done...#"<<std::endl;
}
}
int main()
{
pthread_t c,p;
RingQueue *rq=new RingQueue();
pthread_create(&c,nullptr,consumer,rq);//单消费者
pthread_create(&p,nullptr,productor,rq);//单生产者
pthread_join(c,nullptr);
pthread_join(p,nullptr);
delete rq;
return 0;
}
一种线程的使用模式。
线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着 监督管理者分配可并发执行的任务。
这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利 用,还能防止过分调度。可用线程数量应该取决于
可用的并发处理器、处理器内核、内存、网络sockets等的数量。
//ThreadPool.hpp
#pragma once
#include
#include
#include
#include
#define NUM 5
class Task{
public:
int base;
public:
Task(){}
Task(int _b):base(_b){}
void Run()
{
std::cout<<"task run...done: base#"<<base<<" "<<"pow is#"<<pow(base,2)<<std::endl;
}
~Task(){}
};
class ThreadPool{
private:
std::queue<Task*> q;
int max_num;
pthread_mutex_t lock;
pthread_cond_t cond; //only consumer,thread pool thread;
public:
void LockQueue()
{
pthread_mutex_lock(&lock);
}
void UnlockQueue()
{
pthread_mutex_unlock(&lock);
}
bool IsEmpty()
{
return q.size()==0;
}
void ThreadWait()
{
pthread_cond_wait(&cond,&lock);
}
void ThreadWakeUp()
{
pthread_cond_signal(&cond);//唤醒一个线程
//pthread_cond_broadcast(&cond);唤醒一群
}
public:
ThreadPool(int _max=NUM):max_num(_max)
{}
static void *Routine(void *arg)//static 只能访问static
{
ThreadPool *this_p=(ThreadPool*)arg;
pthread_detach(pthread_self());
while(true){
this_p->LockQueue();//保护任务队列
while(this_p->IsEmpty()){//判断任务队列是否为空
this_p->ThreadWait();
}
Task t;
this_p->Get(t);
this_p->UnlockQueue();
t.Run();
}
}
void ThreadPoolInit()//避免风险
{
pthread_mutex_init(&lock,nullptr);
pthread_cond_init(&cond,nullptr);
pthread_t t;
for(int i=0;i<max_num;i++){
pthread_create(&t,nullptr,Routine,this);
}
}
//server
void Put(Task &in)
{
LockQueue();
q.push(&in);
UnlockQueue();
ThreadWakeUp();
}
//Thread poll
void Get(Task &out)//本身在临界区,已经被锁住了
{
Task*t=q.front();
q.pop();
out=*t;
}
~ThreadPool()
{
pthread_mutex_destroy(&lock);
pthread_cond_destroy(&cond);
}
};
//main.cc
#include"ThreadPool.hpp"
int main()
{
ThreadPool *tp=new ThreadPool();
tp->ThreadPoolInit();
//server
while(true){
int x=rand()%10+1;
Task t(x);
tp->Put(t);
sleep(1);
}
return 0;
}