第二章.进程的描述与控制:2.5经典进程的同步问题


2.5.1 生产者-消费者问题

问题描述:

系统中有一组生产者进程和一组消费者进程,生产者进程每次生产一个产品放入缓冲区,消费者进程每次从缓冲区中取出一个产品并使用。生产者、消费者共享一个初始为空、大小为n的缓冲区。只有缓冲区没满时,生产者才能把产品放入缓冲区,否则必须等待。只有缓冲区不空时,消费者才能从中取出产品,否则必须等待。缓冲区是临界资源,各进程必须互斥地访问。

由于生产者一消费者问题是相互合作的进程关系的一种抽象,例如,在输入时,输入进程是生产者,计算进程是消费者;而在输出时,则计算进程是生产者,而打印进程是消费者,因此,该问题有很大的代表性及实用价值。

1. 利用记录型信号量解决生产者-消费者问题

  • 假定,在生产者和消费者之间的公用缓冲池中,具有n个缓冲区,可利用互斥信号量mutex使诸进程实现对缓冲池的互斥使用;
  • 利用资源信号量empty和full分别表示缓冲池中空缓冲区和满缓冲区的数量;
  • 又假定这些生产者和消费者相互等效,只要缓冲池未满,生产者便可将消息送入缓冲池;只要缓冲池未空,消费者便可从缓冲池中取走一个消息。

对生产者-消费者问题描述如下:

生产者-消费者问题流程:

image-20211121104837109

对临界资源的分析:

image-20211121105224359

划分临界区与加入信号量m:

image-20211121105343545

同步分析:

image-20211121110055615

生产者进程算法描述:

image-20211121110237664

消费者进程算法描述:

image-20211121110327069

同步信号量的定义:

image-20211121110528847

解决方案:

image-20211121111716884

注意:

同步wait操作(wait(empty)和wait(full))应该写在互斥wait操作(wait(m))之前,防止引起进程死锁。释放操作(signal操作)可以无先后顺序。

发生死锁的案例:

image-20211121114848240

伪代码描述:

image-20211121113305269

案例

桌子上有一只盘子,每次只能向其中放入一个水果。爸爸专向盘子中放苹果,妈妈专向盘子中放橘子,儿子专等着吃盘子中的橘子,女儿专等着吃盘子中的苹果。只有盘子空时,爸爸或妈妈才可向盘子中放一个水果。仅当盘子中有自己需要的水果时,儿子或女儿可以从盘子中取出水果。 用PV操作实现上述过程。

问题描述:

image-20211121212747537

问题分析:

image-20211121213203996

代码实现:

image-20211121213426118

注意:

  1. 对于这样设定的问题,即使不设置专门的互斥变量mutex,也不会出现多个进程同时访问盘子的现象。原因在于:本题中的缓冲区大小为1,在任何时刻,apple、orange、plate三个同步信号量中最多只有一个是1。因此在任何时刻, 最多只有一个进程的p操作不会被阻塞,并顺利地进入“临界区”。
  2. 如果缓冲区大小大于1,就必须专门设置一个互斥信号量mutex来保证互斥访问缓冲区。
  3. 无论是多缓冲区还是单缓冲区,都可以加上互斥信号量,保证各进程一定会互斥地访问缓冲区。
  4. 实现互斥的p操作一定要在实现同步的p操作之后,否则可能引起“死锁”。

2. 利用AND信号量解决生产者-消费者问题

image-20211121214625808

3. 利用管程解决生产者-消费者问题

image-20211121215811091 image-20211121215940172

2.5.2 哲学家进餐问题

问题描述:

五个哲学家共用一张圆桌,分别坐在周围的五张椅子上。在圆桌上有五个碗和五支筷子,他们的生活方式是交替地进行思考和进餐。平时,一个哲学家进行思考,饥饿时便试图取用其左、右最靠近他的筷子,只有在他拿到两支筷子时才能进餐。进餐毕,放下筷子又继续思考。

image-20211121220934154

1. 利用记录型信号量解决哲学家进餐问题

image-20211121223150423

上述伪代码逻辑存在的问题:

可能引起死锁,如五个哲学家同时饥饿而各自拿起左筷子时,会使信号量chopstick均为0。因此他们试图去拿右筷子时,都会因无法拿到而无限期等待。

解决方法:

  1. 最多允许4个哲学家同时坐在桌子周围。
  2. 仅当一个哲学家左右两边的筷子都可用时,才允许他拿筷子(and型信号量)。
  3. 给所有哲学家编号,奇数号的哲学家必须首先拿左边的筷子,偶数号的哲学家则先拿右筷子。

2. 利用AND信号量解决哲学家进餐

image-20211121223515738

3. 利用管程解决哲学家进餐问题

image-20211121225632643 image-20211121231317624

2.5.3 读者-写者问题

问题描述:

image-20211122083725240

分类描述:

  • 读者优先描述

    如果读者来:

    1. 无读者、写着,新读者可以读;
    2. 无写者等待,但有其他读者正在读,新读者可以读;
    3. 有写者等待,但有其他读者正在读,新读者可以读;
    4. 有写者写,新读者等。

    如果写者来:

    1. 无读者,新写者可以写;
    2. 有读者,新写者等待;
    3. 有其他写者写或等待,新写者等待
  • 写者优先描述

    如果读者来:

    1. 无读者、写者,新读者可以读;

    2. 无写者等待,但有其他读者正在读,新读者可以读;

    3. 有写者等待,但有其他读者正在读,新读者等;

    4. 有写者写,新读者等。

    如果写者来:

    1. 无读者,新写者可以写;
    2. 有读者,新写者等待;
    3. 有其他写者或等待,新写者等待。

1. 读者优先(利用记录型信号量解决)

为实现Reader与Writer进程间在读或写时的互斥而设置了一个互斥信号量w。 另外,再设置一个整型变量readcount表示正在读的进程数目。由于只要有一个Reader进程在读,便不允许Writer进程去写。因此,仅当readcount=0,表示尚无Reader进程在读时,Reader进程才需要执行wait(w)操作。若wait(w)操作成功,Reader进程便可去读,相应地,做readcount+1操作。同理,仅当Reader进程在执行了readcount减1操作后其值为0时,才须执行signal(mutex)操作,以便让Writer进程写操作。又因为readcount是一个可被多个Reader进程访问的临界资源,因此,也应该为它设置一个互斥信号量mutex。

image-20211122090233231

2. 写者优先(利用信号量集解决)

利用信号量集机制解决读者一写者问题,这里的读者一写者问题,与前面的略有不同,它增加了一个限制,即最多只允许RN个读者同时读。为此,又引入了一个信号量L,并赋予其初值为RN,通过执行wait(L,1,1) 操作来控制读者的数目,每当有一个读者进入时,就要先执行wait(L,1,1)操作,使L的值减1。当有RN个读者进入读后,L便减为0,第RN+1个读者要进入读时,必然会因wait(L,1,1)操作失败而阻塞。对利用信号量集来解决读者一写者问题的描述如下:

image-20211122091028036

其中,Swait(mx,1,0)语句起着开关的作用。只要无进程进入写操作,mx=1,reader进程就都可以进入读操作。但只要一旦有writer进程进入写操作时,其mx=0,则任何reader进程就都无法进入读操作。Swait(mx,1,1,L,RN,0)语句表示仅当既无writer进程在写操作(mx=1)、又无reader进程在读操作(L=RN)时,writer进程才能进入临界区进行写操作。


参考视频:

https://www.bilibili.com/video/BV17h411B7yW?p=28

https://www.bilibili.com/video/BV1YE411D7nH?p=23

参考资料:

《计算机操作系统(第四版)》—— 汤小丹等。

猜你喜欢

转载自blog.csdn.net/weixin_45605541/article/details/121466155
今日推荐