操作系统——进程同步和进程互斥中的经典问题

文章目录

  • 前言
  • 一、生产者消费者问题
  • 二、多生产者多消费者问题
  • 三、吸烟者问题
  • 四、读者写者问题
  • 五、哲学家进餐问题
  • 总结


前言

本文的主要内容是进程同步和进程互斥中的经典问题介绍,包括生产者消费者问题、多生产者多消费者问题、吸烟者问题、读者写者问题以及哲学家进餐问题这五部分,重点理解这五种经典问题中的解题思想。


一、生产者消费者问题

系统中有一组生产者进程和一组消费者进程,生产者进程每次生产一个产品放入缓冲区,消费者进程每次从缓冲区中取出一个产品并使用。
生产者和消费者共享一个初始为空、大小为 n 的缓冲区。只有缓冲区没满时,生产者才能把产品放入缓冲区,否则必须等待;同时只有缓冲区不空时,消费者才能从中取出产品,否则必须等待。(两个同步关系)缓冲区是临界资源,各进程必须互斥地访问。(互斥关系)
生产者消费者问题的示意图如下图所示。
操作系统——进程同步和进程互斥中的经典问题_第1张图片
生产者消费者问题有两个同步关系和一个互斥关系,因此要设置三个信号量,它也是一个驱动关系,需要在前操作后执行 V 操作,在后操作之前执行 P 操作,如下图所示。
操作系统——进程同步和进程互斥中的经典问题_第2张图片
生产者消费者问题分析步骤:
①关系分析,找出题目中描述的各个进程,分析它们之间的同步、互斥关系。
②整理思路,根据各进程的操作流程确定 P、V 操作的顺序。
③设置信号量,并根据题目条件确定信号量的初值,其中互斥信号量的初值一般为1,同步信号量的初始值要根据对应资源的初始值设定。
生产者消费者问题代码实现思路如下图所示。
操作系统——进程同步和进程互斥中的经典问题_第3张图片
需要注意的是,实现互斥是在同一进程中进行一对 P、V 操作,而实现两进程同步是在两个进程中,一个进程实现 P 操作,另一个进程实现 V 操作。
相邻 P 操作的顺序不可交换,即实现同步的 P 操作在前,实现互斥的 P 操作在后。相邻的 V 操作可以互换位置,因为其不会导致进程阻塞。
相邻的 P 操作交换顺序后存在的问题如下图所示。
操作系统——进程同步和进程互斥中的经典问题_第4张图片
实现互斥的 P 操作一定要在实现同步的 P 操作之后。
“生产一个产品”和“使用产品”等非必要代码是可以放在 P、V 操作之间的,但是会导致进程间的并发度降低,因此一般将这种代码放在 P、V 操作外面。

二、多生产者多消费者问题

多生产者多消费者问题描述:桌子上有一只盘子,每次只能向其中放入一个水果。爸爸专门向盘子中放苹果,妈妈专门向盘子中放橘子,儿子专等着吃盘子中的橘子,女儿专等着吃盘子中的苹果,只有盘子为空时,爸爸或妈妈才可以向盘子中放入一个水果,仅当盘子中有自己需要的水果时,儿子或女儿可以从盘子中取出水果。
操作系统——进程同步和进程互斥中的经典问题_第5张图片
该问题中的互斥关系为:对盘子的访问要互斥的进行。
同步关系有:
①父亲将苹果放入盘子后,女儿才能取走苹果。
②母亲将橘子放入盘子后,儿子才能取走橘子。
③只有盘子为空时,父亲或母亲才能放入水果。
在分析同步问题,也就是一前一后的问题时,不能从单个进程行为的角度来分析,而要把一前一后发生的事看做是两种事件的前后关系。
从单个进程行为的角度考虑,则对于该问题有以下结论:如果盘子里装有苹果,那么一定要女儿取走苹果后父亲或母亲才能再放入水果;如果盘子里装有橘子,那么一定要儿子取走橘子后父亲或母亲才能再放入水果。示意图如下图所示。
操作系统——进程同步和进程互斥中的经典问题_第6张图片
正确的分析方法应当是从事件的角度考虑,可以把上述四对进程行为的前后关系抽象为一对事件的前后关系,即盘子变空事件——>放入水果事件。盘子变空事件即可由儿子引发,也可由女儿引发,放入水果事件既可能是父亲执行,也可能是母亲执行,这样分析的话,用一个同步信号量就可以解决问题了。示意图如下图所示。
操作系统——进程同步和进程互斥中的经典问题_第7张图片
多生产者多消费者问题代码实现思路如下图所示。
操作系统——进程同步和进程互斥中的经典问题_第8张图片
在这个问题中,如果不设互斥信号量也是可以实现对盘子的互斥访问的,因为缓冲区的大小为1,在任何时刻,apple、orange 和 plate 三个同步信号量中最多只有一个为1,因此在任何时刻,最多只有一个进程的 P 操作不会被阻塞,并顺利的访问到临界资源。
如果把缓冲区(盘子)的数量设置为2,此时如果不设置互斥信号量,父亲进程和母亲进程会同时访问盘子这个临界资源,这时就可能导致数据覆盖的问题,因此必须设置互斥信号量。
缓冲区的大小为1时,有可能不需要设置互斥信号量就可以实现互斥访问缓冲区的功能。

三、吸烟者问题

吸烟者问题其实就是一个单生产者多消费者问题。
吸烟者问题描述:假设一个系统有三个抽烟者进程和一个供应者进程,每个抽烟者不停地卷烟并抽掉它,但是要卷起并抽掉一只烟,抽烟者需要三种材料:烟草、纸和胶水。三个抽烟者中,第一个拥有烟草,第二个拥有纸,第三个拥有胶水,供应者进程无限地提供三种材料且每次将两种材料放在桌子上,拥有剩下那种材料的抽烟者卷一根烟并抽掉它,并给供应者进程一个信号告诉完成了,供应者就会再放另外两种材料到桌上,这个过程一直重复,让三个抽烟者轮流地抽烟。
操作系统——进程同步和进程互斥中的经典问题_第9张图片
该问题中的互斥关系为:对桌子上物品地访问要互斥的进行。
同步关系有:
①桌子上有纸和胶水,第一个抽烟者取走东西。
②桌子上有烟草和胶水,第二个抽烟者取走东西。
③桌子上有烟草和纸,第三个抽烟者取走东西。
④发出完成信号,供应者再放另外两种材料到桌上。
互斥关系和同步关系表现在图上如下图所示。
操作系统——进程同步和进程互斥中的经典问题_第10张图片
吸烟者问题代码实现思路如下图所示。
操作系统——进程同步和进程互斥中的经典问题_第11张图片
该问题中没有设置互斥信号量,因为缓冲区的数量为1,所以在任何时刻,最多只有一个进程的 P 操作不会被阻塞,并顺利的访问到临界资源。

四、读者写者问题

读者写者问题描述:有读者和写者两组并发进程,它们共享一个文件,当两个或两个以上的读进程同时访问共享数据时不会出现问题,但若某个写进程和其他进程(这里既包括读进程,也包括写进程)同时访问共享数据时则可能导致数据不一致的错误,因此有以下几点要求:
①允许多个读者可以同时对文件执行读操作;
②只允许一个写者往文件中写信息;
③任一写者在完成写操作之前不允许其他读者或写者工作;
④写者执行写操作前,应让已有的读者和写者全部退出。
操作系统——进程同步和进程互斥中的经典问题_第12张图片
该问题中的互斥关系有:写进程和写进程;写进程和读进程。
写进程和任何进程都互斥,可以设置一个互斥信号量 rw,在写者访问共享文件前后分别执行 P、 V 操作,在读者访问共享文件前后也要对互斥信号量 rw 分别执行 P、 V 操作。如果所有读者进程在访问共享文件之前都对互斥信号量 rw 执行 P 操作,那么会导致各个读进程之间也无法同时访问文件。那么怎么解决这个问题呢?
其实对互斥信号量 rw 的 P、 V 操作可以看做是对共享文件的“加锁”和“解锁”,读进程需要同时访问,读进程和写进程又必须互斥访问,那么可以让第一个访问共享文件的读进程“加锁”,让最后一个访问完文件的读进程“解锁”。可以通过设置一个整数变量 count 来记录当前有几个读进程在访问共享文件。
读者写者问题代码实现思路如下图所示。
操作系统——进程同步和进程互斥中的经典问题_第13张图片
为了不使各读进程之间因并发执行而发生阻塞,需要设置一个互斥信号量来保证各读进程对 count 的访问是互斥的。
以后需要实现一气呵成的问题时,应当想到使用互斥信号量。
以上的代码还有一个问题:只要有读进程还在读,写进程就要一直阻塞等待,可能发生饿死,在这种情况下,读进程是优先的。
下图是考虑了写进程饥饿问题后的改进代码,即再引入一个互斥信号量 w。
操作系统——进程同步和进程互斥中的经典问题_第14张图片
这种方法下可以实现多个读进程同时读文件,写者和其他进程不能同时访问文件,写者也不会一直等待,但这种方法也不是真正的写优先,而是相对公平的先来先服务原则,称为读写公平法

五、哲学家进餐问题

哲学家进餐问题描述:一张圆桌上坐着5名哲学家,每两个哲学家之间的桌子上摆一根筷子,桌子中间是一盆食物,哲学家们倾注毕生的精力用于思考和进餐,哲学家在思考时,并不影响其他人,只有当哲学家饥饿时,才试图拿起左、右两根筷子,筷子的拿起是一根一根进行的。如果筷子已经在他人手上,则需要等待,饥饿的哲学家只有同时拿起两根筷子才可以开始进餐,当进餐完毕后,放下筷子继续思考。
操作系统——进程同步和进程互斥中的经典问题_第15张图片
如果按照下面的代码实现,那么很可能出现死锁,即如果第一个人拿起了左边的筷子就发生进程切换,然后依次第二个人也拿起左边的筷子就发生进程切换,这样直到五个人都拿起左边的筷子,最后再切换回任何一个进程,他们都拿不起右边的筷子,因此会发生死锁。
操作系统——进程同步和进程互斥中的经典问题_第16张图片
那么如何防止死锁的发生呢?
方法一:可以对哲学家进程施加一些限制条件,比如最多只允许四个哲学家同时进餐,这样可以保证至少有一个哲学家是可以拿到左右两只筷子的。
方法二:给哲学家编号,然后奇数号的哲学家先拿左边的筷子,再拿右边的筷子,偶数号的哲学家则先拿右边的筷子,再拿左边的筷子,用这种方法就可以保证如果相邻的两个奇偶号哲学家都想吃饭,那么只会有其中的一个可以拿起其中的一只筷子,另一个会直接阻塞,这就避免了一个哲学家占有一只筷子后再等待另一只筷子的情况。
方法三:仅当一个哲学家左右两只筷子都可用时才允许他拿起筷子。
方法三的代码实现思路如下图所示。
操作系统——进程同步和进程互斥中的经典问题_第17张图片
这种方法下,各哲学家拿筷子这件事必须互斥的执行,这就保证了即使一个哲学家在拿筷子拿到一半时被阻塞,也不会有别的哲学家会继续尝试拿筷子,这样的话,当前正在吃饭的哲学家放下筷子后,被阻塞的哲学家就可以获得等待的筷子了。


总结

以上就是操作系统——进程同步和进程互斥中经典问题的所有内容了,这几个经典问题为我们后面解决类似的问题提供了可借鉴的思路,在今后遇到进程同步和进程互斥问题时,可以往这几个经典问题上靠,看看哪个是最适合解决问题的。
参考视频:
生产者消费者问题
多生产者多消费者问题
吸烟者问题
读者写者问题
哲学家进餐问题

你可能感兴趣的:(操作系统,操作系统)