天天看点

操作系统_生产者消费者问题

目录

​​1,生产者消费者问题​​

​​问题的提出​​

​​初步思考​​

​​进程资源共享关系和同步关系分析​​

​​问题的具体解决​​

​​第一搏 ​​

​​存在的问题​​

​​第二搏​​

​​多维度思考​​

​​1,单生产者、单消费者、多缓冲区​​

​​2,多生产者、多消费者、单缓冲​​

​​3,单生产者、单消费者、单缓冲​​

​​4,允许生产者写时,消费者可读​​

​​5,缓冲池无限大​​

​​6,调整生产者wait顺序​​

​​7,调整消费者wait顺序​​

​​8,调整wait顺序(生产者和消费者)​​

​​9,调整signal顺序​​

生产者消费者问题

问题的提出

  • 多个生产者、多个消费者通过共享含n个缓冲区的缓冲池Buffer协作;
  • 其中生产者负责生产数据并投入缓冲池,消费者从缓冲池中取数据消费;
  • 生产者和消费者,每次生产/消费1个数据,要求每个数据必须且只被消费一次;
  • 缓冲池为临界资源。请用记录型信号量进行同步。
操作系统_生产者消费者问题

初步思考

1,生产者可以向未满的缓冲池中放入数据,消费者从非空的缓冲池中取出数据。

2,简化并忽略一些与同步无关的问题:

  • 生产的数据以怎样的顺序放入Buffer?消费者怎样取出(进程何时/怎样被唤醒)?
  • 假设数据按照次序依次放入缓冲区,不需要详细安排;

3,可以想到使用队列来实现数据资源描述,考虑现实中Buffer的实现,为了更充分的利用空间(当队列以数组形式实现时,防止出现假满队列的情况),采用循环队列。生产者生产一个数据,指针in前移,消费者消费一个数据,指针out前移;

操作系统_生产者消费者问题

进程资源共享关系和同步关系分析

1,思考:

  • 几个进程?:两种进程(生产者,消费者);
  • 共享什么样的资源?:生产者进程共享空缓冲区资源;消费者进程共享满缓冲区资源;

2,生产者进程一样,故可用一个模板来描述。消费者相同;

操作系统_生产者消费者问题

问题的具体解决

第一搏 

考虑到有两种临界资源:空/满缓冲区资源,故设计两个资源信号量:full、empty,于是:

操作系统_生产者消费者问题

如图,可以实现:生产者进程共享空缓冲区资源,消费者共享满缓冲区资源,当资源不足时,可以对相应进程阻塞。

存在的问题

以入队为例,当执行完Buffer(in):=nextp时,时间片耗尽,这时又进来了一个生产者进程,空缓冲区资源足够,于是也到了Buffer(in):=nextp这一步,但由于上一个进程刚给in所指位置赋值,in还没来得及前移,in所指位置就又被新的数据覆盖,从而出现错误。

第二搏

问题存在的原因是:声明的变量in和out,此时也成为了临界资源,所以对入队和出队的操作也需要采取信号量机制,形成临界区;

设计互斥信号量:mutex(n.互斥量; 斥体; 互斥; 互斥锁; 互斥对象)

操作系统_生产者消费者问题

至此问题完美解决,上图就是生产者-消费者问题的标准解答!

多维度思考

1,单生产者、单消费者、多缓冲区

操作系统_生产者消费者问题

显然资源信号量:full和empty,不能省略(省去之后,无法标记缓冲区的状态);

若互斥信号量省去,会出现读的同时进行写,或者写的同时进行读;

因此无法简化。

2,多生产者、多消费者、单缓冲

操作系统_生产者消费者问题

此时资源信号量:full和empty初始取值为0,1;

设想运行过程如下:

  1. 开辟消费者进程,但是由于full为0,进入阻塞;
  2. 若仍是消费者进程,仍进入阻塞状态;
  3. 当开辟生产者进程时,empty变为0,在写入数据过程中又有一个生产者进程切换进来,但是此时empty为0,空缓冲资源不足,因此进入阻塞。也就是说此时第一个生产者进程执行完毕释放出full之前,任何生产者/消费者进程都将被阻塞;
  4. 第一个生产者进程释放full后,便唤醒下一个进程。若为生产者进程,则继续阻塞,否则执行消费者进程;
  5. 此后同理

由此可见,这种情况不需要设置互斥信号量mutex,也可实现进程互斥!

代码如下:

操作系统_生产者消费者问题

3,单生产者、单消费者、单缓冲

类似于2的简化版,但是程序仍然同2.

操作系统_生产者消费者问题

4,允许生产者写时,消费者可读

操作系统_生产者消费者问题

标准程序中,设置了一个mutex,使得任何时候只有一个生产者或是消费者进程执行;

为了使写时消费者可读,需要设置两个mutex:mutexP和mutexC,使得消费者与消费者进程、生产者与生产者进程之间互斥,而消费者进程与生产者进程可以同时进行。

操作系统_生产者消费者问题

5,缓冲池无限大

此时空缓冲区资源取之不尽,因此,在生产者在写入数据时不需要考虑申请空缓冲区资源wait(empty);

即可以省略共享信号量empty。

操作系统_生产者消费者问题

6,调整生产者wait顺序

操作系统_生产者消费者问题

如图:

操作系统_生产者消费者问题

当缓冲池放满数据(条件1),empty=0,full=n,又来一个生产者(条件2),在wait(empty)后进入阻塞,此时mutex已被阻塞,那么此后不论来生产者/消费者,都将阻塞,产生死锁!

7,调整消费者wait顺序

操作系统_生产者消费者问题

情况同6类似。

当缓冲池无数据(条件1),empty=n,full=0,又来一个消费者(条件2),在wait(full)后进入阻塞,此时mutex已被阻塞,那么此后不论来生产者/消费者,都将阻塞,产生死锁!

8,调整wait顺序(生产者和消费者)

操作系统_生产者消费者问题

会出现6,7中的问题。

9,调整signal顺序

操作系统_生产者消费者问题

当空缓冲资源empty=0时,此时一消费者进程执行完signal(empty),empty=1,若发生了进程切换(消费者行为已经结束),一生产者进程开始执行,但由于mutex未被上一进程释放,因此生产者虽然有空缓冲资源,却无法正常执行,违反了空闲让进的原则。

继续阅读