利用P/V操作及信号量解决进程间同步问题——生产者&消费者问题

P/V操作

def: P/V操作:由P操作原语和V操作原语组成,其意义是在一个信号量的S上定义了两个操作,该变量的值只能由P操作和V操作进行修改。并且这两个操作均属于原子操作,不可被中断。

//P原语
P(S)          
{ 
S--; //信号量减一
if S<0 //一旦小于0,进入阻塞状态
block ( )} 

//V原语
V(S) `在这里插入代码片`
{ 
S++//信号量加一
if S<=0 //一旦等于0,或者小于0,立即唤醒
wakeup ( )} 

生产者与消费者问题

1.问题描述
  • 荷兰计算机科学家Dijkstra把广义同步问题抽象成一种“生产者与消费者问题”(producer-consumer relationship)的模型。
  • 生产者与消费者可以通过一个环形缓冲池联系起来,环形缓冲池由几个大小相等的缓冲区组成,每个缓冲区容纳一个产品。
  • 每个生产者可不断地每次往缓冲池中送一个生产的产品,而每个消费者则可不断地每次从缓冲池中取出一个产品。
  • 指针 i 和指针 j 分别指出当前的第一个空缓冲区和第一个满缓冲区。刚开始时
    在这里插入图片描述
2.首先需要明确在这个问题中变量代表的含义:
  • mutex:是保证缓冲区使用权互斥的信号量,设初值为1
  • empty: 是指空缓冲区的数目;初值为n
  • full: 是满缓冲区的数目;初值为0
  • 整型量i和j:初值均为0,i指示空缓区序号头指针,j指示满缓 冲区序号头指针。
3.实现代码(伪代码)
/*初始化*/ 
semaphore mutex=1,empty=n,full=0int i=j=0; 
item buffer [n]; 
  • 生产者
void producer( ) /*生产者进程*/ 
{ 
	while(1) 
  { 
	produce next product; 
	P(empty)P(mutex); 
	buffer[i]=product; 
	i=(i+1) % n; 
	V(mutex); 
	V(full); 
  } 
}
  • 消费者
void consumer( ) /*消费者进程*/ 
20 
{ 
	while{ 
	P(full)P(mutex); 
	product =buffer[j]; 
	j=(j+1) % n; 
	V(mutex); 
	V(empty); 
	consume the product; 
  } 
}
void main( ) 
{ 
parbegin (producer( ), consumer( )); //消费者和生产者并发执行;先后顺序不一定,取决于当前的速度
}

以生产者为例:

  1. 检查缓冲区是否满; 如果满,则empty=0;执行p(empty)时,empty–;empty<0;block();生产者进入阻塞状态;(说明无法急需生产,那么睡觉。)等待消费者进入缓冲区进行消费,直到full(empty),才可继续生产
    如果不满,p(empty),empty - 1,进程继续
  2. 通过p(mutex)判断缓冲区内是否有其他进程(消费者)在工作;若有,进入等待队列等待否则,对互斥锁上锁mutex- -,进程继续,
  3. 执行生产操作,生产一个新的商品放入空位
  4. 释放互斥锁v(mutex),mutex++;
  5. v(full),full+ 1 (empty与full此消彼长,总数永远是缓冲池总数n)

思考问题:

  • 无论是生产者还是消费者,关于P操作的次序能否颠倒过来呢?
    P(mutex);
    P(empty);
    P(full);
    P(mutex);

回答:不可颠倒
以生产者为例,先执行p(empty)实现判断缓冲池是否为空,如果缓冲区没空,则通过p(mutex)对缓冲区进行上锁,消费者不能进入缓冲区,一旦empty=0后,说明此时缓冲池以为空,则生产者不会继续执行放入产品的操作,进入阻塞,等待消费者消费,此时还未执行p(mutex),还未对缓冲区上锁,消费者可以进入缓冲区;
而颠倒后,先执行p(mutex)消费者先进入缓冲区,并对缓冲区上锁,再执行p(empty)时发现缓冲区为空,此时缓冲区全部填满,则生产者进入阻塞状态,等待消费者进行消费,而此时消费者通过p(mutex)判断生产者在缓冲区工作,造成生产者出不来,消费者进不去的装填,二者相互等待,进程死锁

如想有更多了解,请戳下方链接:
进程间同步互斥经典问题——生产者与消费者

  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值