进程同步互斥之生产者与消费者问题

1.生产者-消费者问题

生产者消费者问题是一个互斥、同步的综合问题。
对于初学者来说最难的是发现题目中隐含的两对同步关系。
有时候是消费者需要等待生产者生产,有时候是生产者要等待消费者消费,
这是两个不同的“一前一后问题”,因此也需要设置两个同步信号量。

进程同步互斥之生产者与消费者问题_第1张图片

1.问题描述

系统中有一组生产者进程和一组消费者进程,
生产者进程每次生产一个产品放入缓冲区,
消费者进程每次从缓冲区中取出一个产品并使用。(注:这里的“产品”理解为某种数据)
进程同步互斥之生产者与消费者问题_第2张图片

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

2.代码实现

进程同步互斥之生产者与消费者问题_第3张图片

3.不能改变相邻P、V操作的顺序(死锁问题)

进程同步互斥之生产者与消费者问题_第4张图片

  1. 若此时缓冲区内已经放满产品,则empty=0,full=n。
  2. 则生产者进程执行①使mutex变为0,再执行②,
  3. 由于已没有空闲缓冲区,因此生产者被阻塞。
  4. 由于生产者阻塞,因此切换回消费者进程。
  5. 消费者进程执行③,由于mutex为0,即生产者还没释放对临界资源的“锁”,因此消费者也被阻塞。
  6. 这就造成了生产者等待消费者释放空闲缓冲区,而消费者又等待生产者释放临界区的情况,生产者和消费者循环等待被对方唤醒,出现“死锁”。

同样的,若缓冲区中没有产品,即full=0,empty=n。按③④①的顺序执行就会发生死锁。
因此,实现互斥的P操作一定要在实现同步的P操作之后

V操作不会导致进程阻塞,因此两个V操作顺序可以交换。

2.多生产者-多消费者问题

1.问题描述

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

进程同步互斥之生产者与消费者问题_第5张图片

2.互斥关系:( mutex = 1)

对缓冲区(盘子)的访问要互斥地进行。

3.同步关系(一前一后):

  1. 父亲将苹果放入盘子后,女儿才能取苹果
  2. 母亲将橘子放入盘子后,儿子才能取橘子
  3. 只有盘子为空时,父亲或母亲才能放入水果

进程同步互斥之生产者与消费者问题_第6张图片

4.代码实现

进程同步互斥之生产者与消费者问题_第7张图片
进程同步互斥之生产者与消费者问题_第8张图片

  1. 如果缓冲区大小大于1,就必须专门设置一个互斥信号量mutex来保证互斥访问缓冲区,否则就会出现两个进程同时访问缓冲区的情况,有可能导致两个进程写入缓冲区的数据相互覆盖的情况。
  2. 总结:在生产者-消费者问题中,如果缓冲区大小为1,那么有可能不需要设置互斥信号量就可以实现互斥访问缓冲区的功能。当然,这不是绝对的,要具体问题具体分析。
  3. 建议:在考试中如果来不及仔细分析,可以加上互斥信号量,*保证各进程一定会互斥地访问缓冲区。但需要注意的是,实现互斥的P操作一定要在实现同步的P操作之后,否则可能引起“死锁”。

在分析同步问题(一前一后问题)的时候不能从单个进程行为的角度来分析,要把“一前一后”发生的事看做是两种“事件”的前后关系。

即盘子变空事件 → → 放入水果事件。“盘子变空事件”既可由儿子引发,也可由女儿引发;
“放水果事件”既可能是父亲执行,也可能是母亲执行。
这样的话,就可以用一个同步信号量解决问题了.

你可能感兴趣的:(操作系统,服务器,运维,linux)