线程互斥能防止抢占锁,它是对的,但是它不一定合理,以现实为例,现在有一个图书馆,他有个奇怪的规定,他只能一间自习室有一个人自习,墙上有个锁,你抢到了,去自信30分钟,学不了下去了,出去玩之类的,别人是进不了来的,因为锁在你哪里,到了明天,因为锁在你哪里,你能实现开门,学习了一个小时,学不下去了,出去玩,把钥匙挂墙上,过了一会你又想自习了,因为你离墙进,所以你拿到锁比别人快(等于优先级高),
在上帝视角里面,在你在自习的时候外面一大堆人在等着你抢钥匙去自习,你把钥匙放墙上想了想我不能这么颓废又拉回了钥匙,因为你离钥匙进,优先级高,其他人没有抢到钥匙,那么你又开始学不下去,又把钥匙放墙上,想了想又想继续学,其他人在哪里骂骂咧咧的,但是你不以为然,因为你没错,你遵守了规定,一间自习室只能有一个人,但是他没规定那一个人,你是对的,但是因为这样子,你会导致其他人拿不到图书资源,这样子造成了一种饥饿问题,所以互斥是对的,但是它不合适,会导致饥饿问题:一个执行流,长时间得不到资源
游戏规则和之前一样,一间自习室有一个人自习,但是加上了一个新规定,你出去了,把钥匙挂墙上,你不能马上申请进入自习室,你要开始重新排队排到队列的尾部,这样子就让它具有顺序性
在保证临界资源安全的前提下(互斥等),让线程访问某种资源,具有一定的顺序性,我们称之为同步
保证同步是为了防止饥饿性,也为了实现线程协同,也是用来实现合理性

商品是超市制造的吗?答案是,不是的,商品是由供应商制造的,超市只是负责售卖东西,那么问题又来了,为什么消费者不直接向供应商直接购买,比如你要买一盒方便面,供应商会给你吗?答案是不会的,因为它觉得太少了,那么供应商为什么也不直接卖给消费者,因为消费者太分散了,超市不一样,因为大家有个具体地点能去超市买东西,比较集中
优点
1.提高效率
2.解耦(供应商下班了,消费者要买东西,超市能直接给你,因为供应商会生产一定的量,给超市存着,所以消费者买东西不会因为供应商的问题买不了东西)
而上面的东西其实就是缓冲区,消费者是消费线程,超市是临界资源,供应商是生产线程
1.消费者有多个,消费者之间是什么关系呢?
竞争关系,因为商品只有1个的时候就是竞争关系了,用计算机来讲就是互斥
2.供应商有多个,供应商之间是什么关系呢?
也是竞争关系,比如我生产一个品牌的商品,那么你肯定不希望超市售卖其他品牌的商品,用计算机来讲就是互斥
3.消费者和供应商之间又是什么关系呢?
有个消费者要买东西,但是供应商这个时候还没生产完,或者说生产完了,还没放进货架里面,那么消费者还不能购买这个东西,你要等供应商把数据给写入了,才能购买,所以它们要保证互斥关系,供应商要么生产完,要么没生产,但是可以看到你要等供应商生产了,消费者才能购买,这不就是会出现,我们前面讲的合理性的问题吗?所以,要保持同步关系
BlockQueueTest.hpp
#pragma once
#include
#include
#include
#include
#include
using namespace std;
const uint32_t gDefaultCap = 5;//容量
template <class T>
class BlockQueue
{
public:
BlockQueue(uint32_t cap = gDefaultCap)
: cap_(cap)
{
pthread_mutex_init(&mutex_, nullptr);
pthread_cond_init(&conCond_, nullptr);
pthread_cond_init(&proCond_, nullptr);
}
~BlockQueue()
{
pthread_mutex_destroy(&mutex_);
pthread_cond_destroy(&conCond_);
pthread_cond_destroy(&proCond_);
}
public:
//生产接口
void push(const T &in)
{
// 加锁
// 判断->是否适合生产->bq是否为满->程序员视角的条件->1. 满(不生产) 2. 不满(生产)
// if(满) 不生产,休眠
// else if(不满) 生产,唤醒消费者
// 解锁
lockQueue();
if(isFull()) // ifFull就是我们在临界区中设定的条件
{
proBlockWait(); //阻塞等待,等待被唤醒。
}
// 条件满足,可以生产
pushCore(in); //生产完成
unlockQueue();
wakeupCon(); // 唤醒消费者
}
//消费接口
T pop()
{
// 加锁
// 判断->是否适合消费->bq是否为空->程序员视角的条件->1. 空(不消费) 2. 有(消费)
// if(空) 不消费,休眠
// else if(有) 消费,唤醒生产者
// 解锁
lockQueue();
while (isEmpty())
{
conBlockwait(); //阻塞等待,等待被唤醒
}
// 条件满足,可以消费
T tmp = popCore();
unlockQueue();
wakeupPro(); // 唤醒生产者
return tmp;
}
private:
void lockQueue()
{
pthread_mutex_lock(&mutex_);
}
void unlockQueue()
{
pthread_mutex_unlock(&mutex_);
}
bool isEmpty()
{
return bq_.empty();
}
bool isFull()
{
return bq_.size() == cap_;
}
void proBlockWait()
{
// 1. 在阻塞线程的时候,会自动释放mutex_锁
pthread_cond_wait(&proCond_,