对PV操作问题的理解综合

从最初接触PV操作,到有些许理解时候的赞叹,但是具体问题下,自己并不能做到顺畅的分解出问题中的进程与进程之间交织的关系。虽然作者在书中很清晰的总结了一些判断标准。

需要处理的关系只有两种:同步和互斥。
互斥的问题尤其简单,只是设置一个变量mutex,令其初值为1。每个进程进来前先P一下,表示想要用临界区,从临界区出来就要V一下,重置mutex为1。
对于同步问题也并不太难,只需要用变量表示同步进程中间传递的资源数目。这是一个有向图的模型,经常可以用一个看似复杂的有向图的前驱模型来显示PV操作的使用。最简单的便是:从A->B,假设A->B之间设置的信号量是a,那么:A结束后就要V(a),表示V一下a,B在启动之前,首先要P(a),表示P一下a.这样对一个变量的P、V分散在两个进程间,像是在茫茫人海,各执一个信物,表示一种微妙的联系,这个联系叫同步。

还是拿经典的生产者–消费者问题来深入解释。

在生产者–消费者问题中,很容易理解的是对缓冲区的互斥访问,我们设置一个信号量mutex = 1,表示初始可用数为1.
对我来说,我还能体会到第一次看到设置两个信号量:full和empty分别表示空闲缓冲区和满缓冲区的时候,很不理解。
总是以为:full和empty是可以相互推导的关系,何必要设置两个呢?

事实上,这个认识直到现在才真的被打破。我一直忽略了,这里设置两个变量的出发点是我们刚说的A->B这个例子。

这里假设生产者进程是A,消费者进程是B,那么A和B之间的关系除了互斥访问缓冲区外,还有两个同步关系:A->B 和 B->A。

因此必须有两个信号量来表现这两个关系。

那么这两个信号量是什么呢?
A->B ,这里生产者进程结束后,V的是什么呢?V的是生产的东西对吧!所以设计一个full表示缓冲区中已经有的东西,刚好到B准备启动的时候,先P一个full。
同理,B->A,消费者进程消费结束后,需要V一个什么?V的是它用过的空壳子吧!所以设计一个empty来表示缓冲区的空白,在A启动时,先P一下empty。

由此分析,问题就很明确了。

但是或许你会问,怎么推出来的有两道同步关系呢?

既然A和B是面对缓冲区进行的,并没有直接接触,哪里来的同步关系?

这个问题需要看的角度应该是这样的:如果A和B之间没有这两道同步关系,A不管缓冲区空不空,直接生产,B也不管缓冲区有没有东西,直接消费,这样没有限制,一定是混乱的。有一种原则在告诉我们,如果A和B想要进行下去一定是互相牵制的。缓冲区不过是两者之间的一个媒介罢了,真正的关系还是A和B之间。

semaphore mutex = 1;
semaphore empty = n;
semaphore full = 0;

producer()
{
    while(1)
    {
        生产一个;
        P(empty);
        P(mutex);
        放到缓冲区; //访问临界区
        V(mutex);
        V(full);
    }
}

consumer()
{
    while(1)
    {
        P(full);
        P(mutex);
        从缓冲区取出一个; //访问临界区
        V(mutex);
        V(empty);
    }
}

以上。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值