生产者-消费者问题(经典同步问题的详细分析)

生产者-消费者问题

1. 问题描述

一组生产者进程和一组消费者进程共享一个初始为空、大小为n的缓冲区,只有缓冲区为满时,生产者才把消息放入缓冲区,否则必须等待;只有缓冲区不为空时,消费者从中取出消息,否则必须等待。由于缓冲区是临界资源,它只允许一个生产者放入消息,或一个消费者从中取出消息。

2. 问题分析

  1. 生产者与消费者之间对于缓冲区的访问是一个互斥关系。
    • 如果生产者对缓冲区的写入操作不互斥,则可能造成进程p1和进程p2同时获得缓冲区的某个位置为空,进程p1要往缓冲区的该位置写入数据,同时p2也要往该位置写入数据,导致两个进程往其中写入数据的时候出现了数据覆盖的现象。(可能是进程p1先写入数据之后进程p2又立即往相应的位置写入了数据)
    • 如果消费者读取数据的时候没有互斥,则可能造成两个消费者进程同时读取某一段数据,导致各自只读取了数据的一部分,造成读取错误。
  2. 生产者与消费者又是互相协作的一个关系,必须有生产者的生产之后才有消费者的消费,因此生产者与消费者之间又是一个同步的关系。
V
P
生产者
缓冲区
消费者
  1. 实现互斥部分:实现互斥部分要通过PV操作对互斥的代码操作进行互斥加紧:这里也就是生产者对缓冲区的写以及消费者对缓冲区的读。(互斥加紧也就是在互斥代码段前紧跟一个P操作,在互斥代码后紧跟一个V操作)
  2. 对于设置的信号量
    1. 如果mutex的值为0,则P(mutex)操作会导致进程阻塞状态
    2. 如果empty的值为0,则P(empty)操作会导致进程阻塞状态
    3. 如果full的值为0,则P(full)操作会导致进程阻塞状态
  3. 实现同步部分:
    1. 在缓冲区为空时,必须有生产者的写才能有消费者的读操作,如果没有生产者的写,则消费者会由于full值为0而引发p(full)造成的消费者进程阻塞,因而需要一个v(full)操作(来决定是否唤醒消费者进程)在前,一个p(full)操作在后决定是否阻塞消费者进程。因而在producer进程的末尾有一个v(full),在consumer的开头有一个p(full)
    2. 在缓冲区为满时,必须有消费者的读操作,才能有生产者的写操作,因而在producer进程前必须有一个p(empty)操作在empty=0时进行对生产者进程的阻塞,相对应,在consumer进程末尾必须有一个v(empty)进程来决定在empty不再为0的时候唤醒被阻塞的producer进程。
  4. 关于while(1)的作用:保证只要进程没有在被阻塞的状态就能持续不断的接受处理器,保证进程运行的连续性。

3. 进程描述代码

semaphore mutex = 1;//设置临界区互斥信号量
semaphore empty = n;//设置空闲缓冲区
semaphore full = 0;//缓冲区初始化为空

poducer(){
	while(1){
		生产一个产品;
		p(empty);
		p(mutex);
		将产品加入缓冲区;//互斥部分
		v(mutex);
		v(full);
	}
}

consumer(){
	while(1){
		p(full);
		p(mutex);
		从缓冲区取出数据;//互斥部分
		v(mutex);
		v(empty);
	}
}

4. 补充

不能调换p(empty)和p(mutex)的顺序,也不能调换p(full)和p(mutex)的顺序。否则可能在缓冲区为空或者缓冲区为满的时候造成死锁

分析:假如empty=0,mutex=1,则在进行producer进程的时候,首先进行p(mutex),发现mutex为1,缓冲区没有被占用,则给缓冲区上锁,将mutex设置成0,然后再进行p(empty)操作,发现empty为0,将producer进程阻塞,于是缓冲区就处于一个上锁的状态,consumer进程也不能再访问,这就造成了死锁。

  • 15
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值