Chinaunix首页 | 论坛 | 博客
  • 博客访问: 9472543
  • 博文数量: 1293
  • 博客积分: 13501
  • 博客等级: 上将
  • 技术积分: 17974
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-08 18:11
文章分类

全部博文(1293)

文章存档

2019年(1)

2018年(1)

2016年(118)

2015年(257)

2014年(128)

2013年(222)

2012年(229)

2011年(337)

分类:

2012-11-07 16:20:10

一、PV原语的含义

P操作和V操作是不可终端的程序段,成为原语,PV原语及信号量的概念都是由荷兰科学家E.W.Dijkstra提出的。信号量sem是一个整数。Sem大于等于零时代表可供并发进程使用的资源实体数,但sem小于零时则表示正在等待使用临街区的进程数。

原语操作举例如下,P操作与V操作不允许中断:

procedure p(var s:samephore);

{

s.value=s.value-1;

if (s.value<0) asleep(s.queue);

}

 

procedure v(var s:samephore);

{

s.value=s.value+1;

if (s.value<=0) wakeup(s.queue);

}

 

二、P原语操作的动作是:

(p可理解为pass,获得一个资源)

(1) sem减 1 ;

(2) 若sem减 1 后仍大于等于零,则请求的进程继续执行;

(3) 若sem减 1 后小于零,则进程被阻塞后进入与该信号相对应的队列中,然后转进程调度。

image

图 P操作流程

 

V原语操作的动作是:

(V可理解为Release,释放一个资源)

(1) sem加 1 ;

(2) 若相加结果大于零,则请求的进程继续执行;

(3) 若相加结果小于等于零,则从该信号的等待队列中唤醒一个等待进程,然后再返回原进程继续执行或转进程调度。

PV操作对于每一个进程来说,都只能进行一次,而且必须成对使用,在PV原语执行期间不允许有中断的发生。

image

图 V操作流程

 

三、利用信号量和PV操作实现进程互斥的一般模型是:

进程P1 进程P2 …… 进程Pn

…… …… ……

P(S); P(S); P(S);

临界区; 临界区; 临界区;

V(S); V(S); V(S);

…… …… …… ……

其中信号量S用于互斥,初值为1。

使用PV操作实现进程互斥时应该注意的是:

⑴每个程序中用户实现互斥的P、V操作必须成对出现,先做P操作,进临界区,后做V操作,出临界区。若有多个分支,要认真检查其成对性。

⑵P、V操作应分别紧靠临界区的头尾部,临界区的代码应尽可能短,不能有死循环。

⑶互斥信号量的初值一般为1。

 

 

     现在,简单的说一下“信号灯”机制,打一个跟厕所有关的比喻,(不是很雅^_^),在火车上,当A上厕所的时候,他会将厕所的门锁上,对外标识一个“有人”的表示,当他解决完以后,他会打开门,“有人”的标识就会变成“无人”的标识,这样B就可以进去了,而如果A不把这个标识改变,B就算憋死也进不去的。(当然暴力方式排除在外)。C# 提供的 AutoResetEvent就是这样一种“信号灯”,定义这个类的变量,并传递到子线程,在子线程将结束时,将该“信号灯”设置为 true(“无人”)状态,这样主线程就可以进入了(开始执行)。

同样,我们还有上公共厕所的经历,在公共厕所了有很多个便池,当然还有一个厕所管理员,这时,A1,A2,A3……就可以在厕所管理员这里领取一个牌匾,同时进去解决“问题”, 如果,厕所管理员不是很bt,当A1出来的时候,他会放B1进去,但是也有Bt的,非得等到A1,A2,A3……都解决问题了,才让B1,B2,……进去,这就是WaitHandle.WaitAll()WaitHandle.WaitAny(),WaitHandle.WaitOne()的区别,这是可以使用ManualResetEvent的“信号灯”

 

 

典型理解偏差
三个问题:

一,以V原语的1、2步来做,Sem不就永远大于0,那进程不就一直循环执行成为死循环了?

二,Sem大于0那就表示有临界资源可供使用,为什么不唤醒进程?

三,Sem小于0应该是说没有临界资源可供使用,为什么还要唤醒进程?

析疑:

一,P操作对sem减1的。P、V原语必须成对使用!从而不会造成死循环。

二,Sem大于0的确表示有临界资源可供使用,而且这个时候没有进程被阻塞在这个资源上,也就是说没有进程因为得不到这类资源而阻塞,所以没有被阻塞的进程,自然不需要唤醒。

三,V原语操作的本质在于:一个进程使用完临界资源后,释放临界资源,使Sem加1,以通知其它的进程,这个时候如果Sem<0,表明有进程阻塞在该类资源上,因此要从阻塞队列里唤醒一个进程来“转手”该类资源。比如,有两个某类资源,四个进程A、B、C、D要用该类资源,最开始Sem=2,当A进入,Sem=1,当B进入Sem=0,表明该类资源刚好用完, 当C进入时Sem=-1,表明有一个进程被阻塞了,D进入,Sem=-2。当A用完该类资源时,进行V操作,Sem=-1,释放该类资源,而这时Sem<0,表明有进程阻塞在该类资源上,于是唤醒一个。

为了进一步加深理解,再引入二个问题:

四,如果是互斥信号量的话,应该设置信号量Sem=1,但是当有5个进程都访问的话,最后在该信号量的链表里会有4个在等待,也是说S=-4,那么第一个进程执行了V操作使S加1,释放了资源,下一个应该能够执行,但唤醒的这个进程在执行P操作时因S〈0,也还是执行不了,这是怎么回事呢?

五,Sem的绝对值表示等待的进程数,同时又表示临界资源,这到底是怎么回事?

析疑:

四,当一个进程阻塞了的时候,它已经执行过了P操作,并卡在临界区那个地方。当唤醒它时就立即进入它自己的临界区,并不需要执行P操作了,当执行完了临界区的程序后,就执行V操作。

五,当信号量Sem小于0时,其绝对值表示系统中因请求该类资源而被阻塞的进程数目.S大于0时表示可用的临界资源数。注意在不同情况下所表达的含义不一样。当等于0时,表示刚好用完。

阅读(2967) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~