分析进程同步和互斥问题的三步:
- 关系分析:分析问题中的同步(前驱关系)、互斥关系。
- 写出进程:根据问题写出各个进程的P/V操作顺序和必要操作顺序。
- 信号值设置:确定各个PV操作的信号量名称和值。
1.生产者-消费者问题
生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。
1.1问题描述
1.2代码描述
1.3代码分析
2.读者写者问题
2.1问题描述
读者写者问题 描述:有读者和写者两组并发进程,共享一个文件,当两个或以上的读进程同时访问共享数据时不会产生副作用,但若某个写进程和其他进程(读进程或写进程)同时访问共享数据时则可能导致数据不一致的错误。因此要求:
①允许多个读者可以同时对文件执行读操作;
②只允许一个写者往文件中写信息;
③任意一个写者在完成写操作之前不允许其他读者或写者工作;
④写者执行写操作前,应让已有的读者和写者全部退出。
图示:
2.2问题分析
2.3代码
2.4代码分析
缺点1:在上面的算法中,读进程是优先的,即当存在读进程时,写操作将被延迟,且只要有一个读进程活跃,随后而
来的读进程都将被允许访问文件。这样的方式会导致写进程可能长时间等待,且存在写进程“钱死”的情况。
缺点2:若两个读进程并发执行,则count=0时两个进程也许都能满足f条件,都会执行P(rw),从而使第二个读进程阻塞的情况。
如何解决:出现上述问题的原因在于对count变量的检查和赋值无法一气呵成,因此可以设置另一个互斥信号量来保证各读进程对count 的访问是互斥的。
改进思路:若希望写进程优先,即当有读进程正在读共享文件时,有写进程请求访问,这时应禁止后续读进程的请求,等到已在共享文件的读进程执行完毕,立即让写进程执行,只有在无写进程执行的情况下才允许读进程再次运行。
改进方法:增加一个信号量并在上面程序的writer()和reader(),中各增加一对PV操作,就可以得到写进程优先的解决程序。
2.5代码改进
2.6代码解释
这里的写进程优先是相对而言的,有些书上将这个算法称为读写公平法,即读写进程具有一样的优先级。当一个写进程访问文件时,若先有一些读进程要求访问文件,后有另一个写进程要求访问文件,则当前访问文件的进程结束对文件的写操作时,会是一个读进程而不是一个写进程占用文件(在信号量w的阻塞队列上,因为读进程先来,因此排在阻塞队列队首,而V操作唤醒进程时唤醒的是队首进程),所以说这里的写优先是相对的。
2.7代码特点
读者-写者问题有一个关键的特征,即有一个互斥访问的计数器count,因此遇到一个不太好解决的同步互斥问题时,要想一想用互斥访问的计数器count能否解决问题。
3.哲学家进餐问题
3.1问题描述
一张圆桌边上坐着5名哲学家,每两名哲学家之间的桌上摆一根筷子,两根筷子中间是一确米饭,如下图,哲学家们倾注毕生精力用于思考和进餐,哲学家在思考时,并不影响他人。只有当哲学家饥饿时,才试图拿起左、右两根筷子(一根一根地拿起)。若筷子已在他人手上,则需要等待。饥饿的哲学家只有同时拿到了两根筷子才可以开始进餐,进餐完毕后,放下筷子继续思考。
3.2问题分析和信号量设置
3.3代码及描述(不完善版)
3.4代码及描述(改进版)
4.吸烟者问题
4.1问题描述
假设一个系统有三个抽烟者进程和一个供应者进程。
- 每个抽烟者:不停地卷烟并抽掉它,但要卷起并抽掉一支烟,抽烟者需要有三种材料:烟草、纸和胶水。
- 三个抽烟者中:第一个拥有烟草,第二个拥有纸,第三个拥有胶水。
- 供应者进程:无限地提供三种材料,供应者每次将两种材料放到桌子上,拥有剩下那种材料的抽烟者卷一根烟并抽掉它,并给供应者一个信号告诉已完成,此时供应者就将另外两种材料放到桌上,如此重复(让三个油烟者轮流地抽烟)。
4.2问题分析
关系分析:供应者与三个抽烟者分别是同步关系。由于供应者无法同时满足两个或以上的抽烟者,三个抽烟者对抽烟这个动作互斥(或由三个抽烟者轮流抽烟得知)。
整理思路:这里有4个进程。供应者作为生产者向三个抽烟者提供材料。
信号量设置:信号量offer1,offer2,offer3分别表示烟草和纸组合的资源、烟草和胶水组合的资源、纸和胶水组合的资源。信号量finish用于互斥进行抽烟动作。
4.3代码描述