文章目录
教程
- 生产者消费者问题
https://www.bilibili.com/video/BV1YE411D7nH/?p=23&share_source=copy_web&vd_source=d228985826b563972268952905224139 - 多生产者-多消费者https://www.bilibili.com/video/BV1YE411D7nH/?p=24&share_source=copy_web&vd_source=d228985826b563972268952905224139
- 吸烟者问题 https://www.bilibili.com/video/BV1YE411D7nH/?p=25&share_source=copy_web&vd_source=d228985826b563972268952905224139
- 读者-写者问题
https://www.bilibili.com/video/BV1YE411D7nH/?p=26&share_source=copy_web&vd_source=d228985826b563972268952905224139 - 哲学家进餐问题 https://www.bilibili.com/video/BV1YE411D7nH/?p=27&share_source=copy_web&vd_source=d228985826b563972268952905224139
- 管程 https://www.bilibili.com/video/BV1YE411D7nH/?p=28&share_source=copy_web&vd_source=d228985826b563972268952905224139
1. 生产者消费者问题
1.1 问题描述
1.2 问题分析
1.3 思考:能否改变相邻P、V操作的顺序?
1.4 总结
2. 多生产者-多消费者
2.1 问题描述
桌子上有一只盘子,每次只能向其中放入一个水果。爸爸专向盘子中放苹果,妈妈专向盘子中放橘子,儿子专等着吃盘子中的橘子,女儿专等着吃盘子中的苹果。只有盘子空时,爸爸或妈妈才可向盘子中放一个水果。仅当盘子中有自己需要的水果时,儿子或女儿可以从盘子中取出水果。用PV操作实现上述过程。
2.2 问题分析
2.3 如何实现
2.5 总结
总结:在生产者-消费者问题中,如果缓冲区大小为1,那么有可能不需要设置互斥信号量就可以实现互斥访问缓冲区的功能。当然,这不是绝对的,要具体问题具体分析。
建议:在考试中如果来不及仔细分析,可以加上互斥信号量
,保证各进程一定会互斥地访问缓冲区。
但需要注意的是,实现互斥的P操作一定要在实现同步的P操作之后,否则可能引起“死锁”。
PV 操作题目的解题思路:
- 关系分析。找出题目中描述的各个进程,分析它们之间的同步、互斥关系。
- 整理思路。根据各进程的操作流程确定P、V操作的大致顺序。
- 设置信号量。设置需要的信号量,并根据题目条件确定信号量初值。(互斥信号量初值一般为1,同步信号量的初始值要看对应资源的初始值是多少)
3. 吸烟者问题
假设一个系统有三个抽烟者进程和一个供应者进程。每个抽烟者不停地卷烟并抽掉它,但是要卷起并抽掉一支烟,抽烟者需要有三种材料:烟草、纸和胶水。三个抽烟者中,第一个拥有烟草、第二个拥有纸、第三个拥有胶水。供应者进程无限地ᨀ供三种材料,供应者每次将两种材料放桌子上,拥有剩下那种材料的抽烟者卷一根烟并抽掉它,并给供应者进程一个信号告诉完成了,供应者就会放另外两种材料再桌上,这个过程一直重复(让三个抽烟者轮流地抽烟)
3.1 问题分析
假设一个系统有三个抽烟者进程
和一个供应者进程
。每个抽烟者不停地卷烟并抽掉它,但是要卷起并抽掉一支烟,抽烟者需要有三种材料:烟草、纸和胶水。三个抽烟者中,第一个拥有烟草、第二个拥有纸、第三个拥有胶水
。供应者进程无限地供三种材料,供应者每次将两种材料放桌子上,拥有剩下那种材料的抽烟者卷一根烟并抽掉它
,并给供应者进程一个信号告诉完成了
,供应者就会放另外两种材料再桌上,这个过程一直重复(让三个抽烟者轮流地抽烟
)
本质上这题也属于“生产者-消费者”问题,更详细的说应该是“可生产多种产品的单生产者-多消费者”。
- 关系分析。找出题目中描述的各个进程,分析它们之间的同步、互斥关系。
- 整理思路。根据各进程的操作流程确定P、V操作的大致顺序
- 设置信号量。设置需要的信号量,并根据题目条件确定信号量初值。(互斥信号量初值一般为1,同步信号量的初始值要看对应资源的初始值是多少)
3.2 总结
吸烟者问题可以为我们解决“可以生产多个产品的单生产者
”问题提供一个思路。
值得吸取的精华是:“轮流让各个吸烟者吸烟”必然需要“轮流的在桌上放上组合一、二、三”,注意体会我们是如何用一个整型变量 i 实现这个“轮流”过程的。
如果题目改为“每次随机地让一个吸烟者吸烟”,我们有应该如何用代码写出这个逻辑呢?
若一个生产者要生产多种产品(或者说会引发多种前驱事件),那么各个V操作应该放在各自对应的“事件”发生之后的位置。
4. 读者-写者问题
4.1 问题描述
有读者和写者两组并发进程,共享一个文件,当两个或两个以上的读进程同时访问共享数据时不会产生副作用,但若某个写进程和其他进程(读进程或写进程)同时访问共享数据时则可能导致数据不一致的错误。因此要求:①允许多个读者可以同时对文件执行读操作;②只允许一个写者往文件中写信息;③任一写者在完成写操作之前不允许其他读者或写者工作;④写者执行写操作前,应让已有的读者和写者全部退出。
4.2 如何实现
4.3 总结
读者-写者问题为我们解决复杂的互斥问题提供了一个参考思路。
其核心思想
在于设置了一个计数器 count
用来记录当前正在访问共享文件的读进程数。我们可以用count 的值来判断当前进入的进程是否是第一个/最后一个读进程,从而做出不同的处理。
另外,对 count 变量的检查和赋值不能一气呵成导致了一些错误,如果需要实现“一气呵成”,自然应该想到用互斥信号量
。
最后,还要认真体会我们是如何解决“写进程饥饿”问题的。
绝大多数的考研PV操作大题都可以用之前介绍的几种生产者-消费者问题的思想来解决,如果遇到更复杂的问题,可以想想能否用读者写者问题
的这几个思想来解决。
5. 哲学家进餐问题
一张圆桌上坐着5名哲学家,每两个哲学家之间的桌上摆一根筷子,桌子的中间是一碗米饭。哲学家们倾注毕生的精力用于思考和进餐,哲学家在思考时,并不影响他人。只有当哲学家饥饿时,才试图拿起左、右两根筷子(一根一根地拿起)。如果筷子已在他人手上,则需等待。饥饿的哲学家只有同时拿起两根筷子才可以开始进餐,当进餐完毕后,放下筷子继续思考。
5.1 问题分析
一张圆桌上坐着5名哲学家,每两个哲学家之间的桌上摆一根筷子,桌子的中间是一碗米饭。哲学家们倾注毕生的精力用于思考和进餐,哲学家在思考时,并不影响他人。只有当哲学家饥饿时,才试图拿起左、右两根筷子(一根一根地拿起)。如果筷子已在他人手上,则需等待。饥饿的哲学家只有同时拿起两根筷子才可以开始进餐,当进餐完毕后,放下筷子继续思考。
5.2 总结
哲学家进餐问题的关键在于解决进程死锁
。
这些进程之间只存在互斥关系,但是与之前接触到的互斥关系不同的是,每个进程都需要同时持有两个临界资源,因此就有“死锁”问题的隐患。
如果在考试中遇到了一个进程需要同时持有多个临界资源的情况,应该参考哲学家问题的思想
,分析题中给出的进程之间是否会发生循环等待,是否会发生死锁
。
可以参考哲学家就餐问题解决死锁的三种思路。
6.管程
6.1为什么要引入管程
6.2 管程的定义和基本特征
管程是一种特殊的软件模块
,有这些部分组成:
-
局部于管程的
共享数据结构
说明; -
对该数据结构进行操作的
一组过程
; -
对局部于管程的共享数据
设置初始值
的语句; -
管程有一个
名字
。
跨考Tips: “过程”其实就是“函数”
管程的基本特征:
-
局部于管程的数据
只能被局部于管程的过程
所访问; -
一个进程只有
通过调用管程内的过程
才能进入管程访问共享数据;
-
每次仅允许一个进程在管程内执行某个内部过程
。