cp是高效的:consumer在临界区,productor在非临界区,处于并发的过程
伪唤醒问题
假设只有唯一一个资源,消费进程一被唤醒获取资源,并释放锁,此时消费进程二竞争锁胜于生产进程,从pthtead_cond_wait唤醒执行,并直接跳过了判断环节,导致向空资源获取资源。
用while来判断解决伪唤醒
while(q_.size()==0)
{// 申请锁成功,发现队列为空了,释放锁,这个线程挂起pthread_cond_wait(&cond_,&mutex_);
}while(q_.size()==maxcap_)
{// std::cout<<"线程已满"<<std::endl;// 申请锁成功,发现队列满了,释放锁,这个线程挂起,pthread_cond_wait(&pond_,&mutex_);
}
修改成多线程
for (int i=0;i<3;i++){pthread_create(c+i,nullptr,Consumer,bq);}for (int i=0;i<5;i++){pthread_create(p+i,nullptr,Consumer,bq);}for (int i=0;i<3;i++){pthread_join(c[i],nullptr);}for (int i=0;i<3;i++){pthread_join(p[i],nullptr);}
多个生产者和消费者都是一把锁,维持了互斥原则
且用两个条件变量,保证消费者和生产者的同步原则
信号量
共享资源可以看成多份,用信号量决定多少个进程访问,确保访问共享资源的线程数量不超过共享资源份数。
每个执行流,想访问共享资源的一部分,不是直接访问,而是先申请计数器资源
信号量接口
环形队列的消费模型
特点
规定:指向同一个位置,只能一个人访问
当两者同时指向同一个资源时,为空或者满
当为空时只能生产者访问,为满时只能消费者访问
消费者不能超过生产者
且消费者不能套圈
用信号量来实现
Productor 关注剩余空间 SpaceSem:N(N为队列大小)
Consumer 关注剩余数据 DataSem:0
生产者 每次生产数据P(SpaceSem) 空间资源-1
消费者 每次消费数据时P(DataSem) 数据资源-1
生产的过程中V(DataSem) 数据资源+1
消费的过程时 V(SpaceSem) 空间资源+1
空时,生产者和消费者指向同一位置,但数据资源为0,不能消费
满时,生产者和消费者指向同一位置,空间资源为0,不能生产
以此来维持环形队列,不被套圈等性质。