文章目录
- 经典的信号量同步问题
-
- 第一部分 生产者消费者问题
- 1、多生产者多消费者 -- 吃水果
- 2、单生产者多消费者问题 -- 吸烟者
- 3、多生产者问题 -- 仓库存货物
- 4、多生产者-单消费者问题
- 5、自行车生产线 -- 解决死锁问题
- 6、多生产者多消费者 -- 消费者连续消费
- 7、既是生产者 又是消费值
- 第二部分 营业员 - 顾客问题
- 1、面包店卖面包问题
- 2、营业员 -- 顾客问题
- 第三部分 关于门、路、桥的问题
- 1、博物馆参观 -- 进门出门问题
- 2、大桥过车问题
- 第四部分 哲学家进餐问题
- 1、哲学家进餐问题1
- 2、哲学家进餐问题2
- 第五部分 有趣的生活问题
- 1、老和尚喝水 -- 小和尚打水问题
- 2、理发师理发问题⚑
- 3、放电影问题
- 4、读者 -- 写者问题
- 第六部分 结合程序代码分析问题
- 1、结合线程的同步-互斥问题
- 2、三个合作进程完成计算操作
经典的信号量同步问题
第一部分 生产者消费者问题
1、多生产者多消费者 – 吃水果
-
互斥关系
对缓冲区的访问需要互斥的进行
消费者与消费者之间为什么有互斥关系呢?因为消费者需要将缓冲区的内容取走,改变了缓冲区的内容。
-
同步关系
女儿等待父亲放苹果 儿子等待母亲放橘子
父亲或母亲等待盘子中的水果被取走 盘子为空才可以放水果 而盘子为空这个事件既可以由儿子触发 也可以由女儿触发 只要触发就可以允许父亲进程和母亲进程放水果
-
对于缓冲区的个数需要设置同步信号量来标识
如果缓冲区的数目为1的话,那么同一时刻只会有一个进程访问临界区资源,不会导致互斥问题,有可能不需要设置 互斥信号量 就可以实现 互斥访问缓冲区的功能
另一个角度:
同一个时刻只有1个同步信号量的值为1,也就只有一个进程的P操作不会被阻塞,也就实现了进程的互斥如果缓冲区大于1的时候,对于多个生产者就需要设置互斥信号量实现互斥的访问临界资源,否则每个生产者进程对临界区的空闲个数进行P操作都可以访问临界区。
-
分析过程
-
分析同步问题
不能从单个进程行为的角度来考虑,而是考虑同步关系事件的先后关系,具体为谁在等待谁释放的什么资源
对多个消费者 与 多生产者之间的一类(多个)同步关系,并不是每个同步关系对应一个同步信号量, 抽象成 一对事件的先后关系
比如:
对单个进程来分析:
-
儿子取走橘子 导致 父亲可以放苹果
-
儿子取走橘子 导致 母亲可以放橘子
-
女儿取走苹果 导致 父亲可以放苹果
-
女儿取走苹果 导致 母亲可以放橘子
可以抽象成一对事件的先后关系
- 取走水果盘子变空事件 导致 放水果事件
这样就可以使用一个同步信号量来解决问题
-
-
2、单生产者多消费者问题 – 吸烟者
分析
完成信号量初始值为0
生产者在生产某一种组合的时候,没有先去等待抽烟者完成,而是先去准备东西,因为最开始是没有人抽烟的,对完成信号量(初始值为0)进行P操作的话会被阻塞。
因此先进行某种组合的V操作,然后对完成信号量进行P操作等待抽烟者取走,如果有抽烟者在抽烟,就进入等待队列,当完成信号量V之后唤醒。
缓冲区信号量初始值1
对上面的解决也可以采用共享缓冲区的数量作为同步信号量,初始值为1
这样生产者每次生产之前先对缓冲区数量进行P操作,代表桌子上没有空位置了,等待抽烟者抽完,对缓冲区信号量进行V操作「类似上面问题的盘子信号量」
3、多生产者问题 – 仓库存货物
分析
-
进程只有放A产品 进程 和 放B产品进程
-
关系
-
互斥:
每次只能放入一种产品 放A产品和放B产品需要互斥的访问临界资源(仓库)
-
同步
这里A放入的时候要考虑 A还能与B是否还能满足数量差(>=0)
放B之前也要考虑B还能与A容纳的数量差
设置同步信号量Sa 和 Sb分别代表A 与 B还可容纳的数量差
放A的进程中
-
首先要对Sa进行P操作,检查数量差是否还允许A放入
每次放进去一个A产品,A产品与B产品的数量差就要减一;
-
当放完之后,要对Sb进行V操作
为什么呢?
因为起初A和B产品的数量都是从0开始的,当放入A产品之后,A的产品数量增加了,大于0,受Sa的影响只能放入有限的A产品,然后Sb代表的是相对于A来说允许的差量值,应该是对A现在产品数量再加上Sb的值,但是B产品起初是0,如果B产品放之间对Sb进行P操作,这样只是假设在A产品0件的基础上进行放B产品,因此需要在A产品放入之后,对B与A之间容纳的差量值Sb也要进行V操作,此时Sb变大了,当B产品一直放当追上A产品数量之后,就按照初始的N值进行放B产品,实现相对于A当前数量进行放B产品「在可容纳的差量值之前」
实际上,B产品在追上A产品数量之前,是由A与B的差量值M控制的「因为此时A已经比B多m-1件了,达到允许的差量最大值,便不再放A,但是B可以放呀,B放之后,对Sa进行V操作,又唤醒了放A产品的进程,因为B产品的放入仓库,导致A与B之间的实际差量值又小于可容纳最大差量值M了,所以A又可以愉快的放入库中了」,追上之后按照B与A的差量值(N)进行控制
-
-
解答
4、多生产者-单消费者问题
分析
-
进程
这里有三个进程:
- 生产车间生产A产品并放入F1货架的进程
- 生产车间生产 B产品并放入F2货架的进程
- 装配车间分别从货架F1和货架F2上取得A、B零件组装产品进程
-
关系
-
互斥
这里货架属于互斥缓冲区资源,在放入零件和取出零件的时候不允许两个进程同时访问货架临界区资源,防止它们对货架上的同一个位置放零件,这是不允许的。
因此需要设置mutex对货架进行互斥的访问
-
同步
这里放零件A到货架上的进程需要等待组装进程取走货架上的零件而产生的空闲位置
而组装进程需要等待放零件进程放入货架之后充满一个位置因此需要对F1货架的A零件和货架F2的B零件分别设置empty(=10)和full(=0)同步变量来记录货架缓冲区是否为空,是否未满
-
解答
5、自行车生产线 – 解决死锁问题
分析
这里的问题与前面的多生产者单消费者问题类似,不同的地方在于前面的多生产者生产的东西不是放到同一个缓冲区资源里,因此即使第一个生产者将货架放满了,生产者2还是可以生产放入另一个货架的,这样消费者就可以从各个货架分别取零件然后第一个生产者进程就被唤醒了。
这里是将不同生产者的零件都放到同一个箱子里,这个箱子就是互斥临界资源,当第一个生产者的零件充满临界资源之后就需要等待消费者取走几个零件然后唤醒此进程,但是此时生产者2因为箱子无空间无法生产零件,导致消费者无法取得生产者2生产的零件而被阻塞,这样3个进程权都被堵塞而互相等待,这就产生了死锁。因此不能让某个生产者一直生产零件而占满互斥缓冲区。
-
进程
2个生产者进程 1个消费者进程
-
关系
-
互
-