MyException - 我的异常网
当前位置:我的异常网» 系统运维 » pv操作兑现多进程同步和互斥

pv操作兑现多进程同步和互斥

www.myexceptions.net  网友分享于:2013-04-10  浏览:52次
pv操作实现多进程同步和互斥

       本篇文章,讲解了PV操作的作用,举了两个情景模拟pv操作的应用原理,同时讲解了PV操作涉及到的基本概念,并且在文章的最后用伪代码写了pv操作过程。

 

       要理解PV操作,请先看两个场景:

 

场景1:飞机场售票窗口进程

Process Pi(i=1,2,3,…,n)

Begin

	查找当天机票剩余量A

	If A>1 then

		A=A-1;

		售出一张票

	Else 输出票以售完

End

 

       若同时有5个窗口执行该程序,如果5个程序同时并发执行,同时取到相同的票数(实际情况中:用锁就能解决该问题,不会取到相同的票数,此处只是为说明pv操作),则售了5张票,而实际票数只减了1张。

 

       场景2:进程A向缓存中写数据(缓存只存一条数据),进程B从缓存存数据。如果在B未取走数据前就写入数据,数据会被覆盖;若A还没写入新数据前B写入一次数据,则会读取到旧数据,怎么保证两个进程能够同步执行?

 

        情景一为互斥问题,当一个进程读取并修改数据的时候,另一个进程不能读取数据;情景二为同步问题,只有在进程A写入数据后,B才能读数据,否则可能读到空数据或者重复数据;B读取完,A才能写入数据,否则可能数据还没有读的时候就被覆盖掉。

 

使用PV操作可以解决上面的两个问题,pv操作通过观察信号量,从而控制多个进程间同步或互斥使用资源。

理解PV操作需要理解几个重要的概念:临界区,P操作,V操作,同步和互斥。

 

进程的互斥:若干个进程都要访问某一共享资源时,任何时刻最多只允许一个进程使用该资源,其他要使用该资源的进程必须等待,知道该资源的占用者释放进程。

进程的同步:并发进程间存在一种制约关系,一个进程的执行依赖另一个进程的消息,当一个进程没有得到另一个进程的消息时等待,知道消息到达才被唤醒。

 

临界区:当N个进程都要访问同一个变量时,我们把与共享变量有关的程序段成为临界区。所有涉及该变量的临界区成为相关临界区。

信号量:表示临界区的进程是否可以往下执行,用S signal 代表信号量 ,s>0,代表当前变量或资源可以使用,该进程可以执行;S=0,表示当前无资源,当前进程不可往下执行;s<0表示当前有等待使用资源的进程,并且该负数的绝对值代表等待资源的进程数

p操作:判断调用P操作的进程是否可以获得资源并往下执行,如果信号量减一后大于0,将会往下执行,否则继承进入等待队列;

用代码表示:

Procedure P(Var S:Semaphore);

Begin

	s=s-1;

	If s<0 then W(s);

End;{P}

 

V操作:进程释放一个变量或资源,信号量加一,若等待队列有进程,则释放一个等待进程(该进程获取资源并执行)

Procedure V(Var S:Semaphore);

Begin

	s=s+1

	if S<=0 then r(s)

end


 

那么了解了PV操作和相关的概念后,我们可以试着用PV操作解决文章开始的两个场景了:

解决场景一:将PV操作将如到场景一的伪代码中

 

Begin

S:semaphore  //定义信号量

S=1;

Process Pi(i=1,2,3,…,n)

	Begin

		查找当天机票剩余量A

		P(S);           //进行P操作,当前的信号量减1大于等于0,则继续进行,否则等待资源

		If A>1 then

			A=A-1;

			V(S)             //将当前变量或资源释放,将信号量加一,结果如果小于等于0,则唤醒一个进程

			售出一张票

	Else 输出票以售完

	End

End

 

        那么此时,由于将信号量设置为1,只能有一个进程访问并修改机票数量,因此不会出现问题。

       有此可见,当信号量为正时,信号量的数值代表有几个可用资源,为0时,表示当前没有可用资源,为负值时说明当前有进程在等待资源。

 

解决场景二:

Begin

Buffer:integer

SA,SB:semaphore;

SA=1,SB=0;//定义A进程的信号量和B进程的信号量

Process A

	Begin

		L1:  向缓存中写入一个数据Data;

		P(SA);         //进行P操作,判断当前进程A是否可以向缓存写入数据

		Buffer=Data;

		V(SB);              //A进程写入说后,将B进程的信号量加一,告诉B进程可以进行读数据了

		Goto L1;

	End ;

Process B

	Begin

		L2:     P(SB);                                         //进行P操作,判断当前进程B是否可以从缓存读数据

		从缓存取出一个数据Data;

		V(SA);                 //读完数据后,将A进程的信号量加一,告诉A进程可以写入数据了

		用取出的数据进行计算;

		Goto L2;

	End

End 


 

PV操作解决了多个进程间共享数据和资源时,误操作的问题,保证了安全的共享资源。

 

 

 

 

 

1楼lfmilaoshi昨天 15:12
01.Procedure V(Var S:Semaphore); n02. n03.Begin n04. n05. s=s+1 n06. n07. if S<0 then r(s) “这里有错误,应当是 if S<=0 then R(s)n08. n09.end
Re: xqf3092小时前
回复lfmilaoshin嗯,信号量S应该小于等于0

文章评论

软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有