关于多线程(进程)死锁的探测

正式干上程序员这一行也有几年了。时间虽短,但感触颇有一些。现如今,我们的计算机硬件已今非昔比了——好一点的PC服务器都有八个甚至于更多的CPU(虽然实际上是多核的,物理上也许只有那么两三个,但对于软件系统来说,这没什么分别),内存多达四五个GB。可是我们有没有发现,我们的应用对于这么多的资源的利用是不是不允分。

多线程编程是允分利用这些资源的利器。但很多时候这个利器是那么的钝——为了在多线程中保证事条逻辑的一致性、资源的独占性,我们不得不使用各种各样的锁机制(资源独占机制)。线程一多,我们就开始担心是否出现死锁。虽然,在程序中,我们可以人为的限定资源的锁定顺序或是使用在某一时刻只锁一个资源的方式,来在一定程度上防止死锁的发生。但这也不是万无一失的,很多时候,我们会去调用别人的程序,而很多时候我们是无法知道别人的代码是怎么编写的。实际上刻意避免死锁的发生是不必要的,也是不现实的——防守的再严密,它都会在不经意见光顾我们。我们不需要在这方面下太多心思,我们需要做的是,在死锁还未发生时或发生的那一瞬间发现它,向造成死锁的线程或进程抛出这个异常,由它们自己去处理这些死锁情况,而保证其它的线程或进程能正常运行下去。

现在的关键问题就是,我们怎么发现这些个死锁。这就是我后面要说的死锁探测算法——待锁定环探测算法(实际上是死锁的定义,这个定义本身就是死锁的探测算法)。下面,我来说明一下什么是死锁?死锁是如何形成的?死锁在“数学”上是什么形态的?

资源的状态

在此之前,我们需要明确一下资源对于线程(进程)的一些状态。一个资源对于任何线程或进程来说,都有三种状态:

Ø         被拥有(态)
一个进程或线程一旦锁定了某个资源,对于这个进程或线程而言,这个资源就进入了被拥有态。

Ø         被等待(态)
某个资源被其它线程或进行所拥有,一个线程或进程还想去拥有它。这时,对于这个进程或线程而言,这个资源进入了被等待态

Ø         被忽视(态)
当一个进程或线程,使用完某个资源后将它释放,或在某段时间内根本不对这个资源感兴趣时,对于这个进程或线程而言,这个资源进入了被忽视态。

这三种状态,对于资源来说,可以同时成立,也可以只有一部分成立。但对于某个<资源,进程(线程)>偶对(关系)来说,只可能是三选一的。对于被拥有(态)来说,只有一个<资源,进程(线程)>偶对存在。

线程或进程的三个集合

由资源的三种状态,可以得知,关于资源,线程(进程)必然有三个从属的集合,分别是:

Ø         被拥有资源集合(简称X集合)

Ø         被等待资源集合(简称Y集合)

Ø         被忽视资源集合(简称Z集合)

集合内的元素,分别是与进程或线程成三种关系的资源。

死锁的探测

要探测死锁,就必须去考察以上说有三个集合。其中,Z集合可以不被考察,它对于死锁的探测没有什么作用。

一个线程或进程的三个资源集合,是动态的,随着资源的分配而动态改变。这一点大家必须要清楚。由于Z集合不被考察,在此仅就X集合、Y集合来论计一下它们的特点——重点是Y集合。

被等等待资源集合(Y集合)

由于线程或进程是串行执行的,某个时刻,只能对一个资源加锁。此时若请求的资源被别人拥有,那么这个资源就会进入到这个线程或进程的Y集合中去。而线程或进程在此时会阻塞。由此可知,Y集合中的元素要么没有,如果有,必然也会只有一个(实际对于多线程进程而言,它的Y集合不一定最多只有一个元素,但对于多线程进程,我们不考察它而考察它里面的线程)。

当请求的资源被其它线程或进程释放后,资源就顺理成章的被现在的这个线程或进程所拥有(这里假设这一时间里只有它要求拥有这个资源)。此时,Y集合中元素就会变为X集合中的元素。

被拥有资源集合(X集合)

被某个线程或进程拥有的资源对象,都是这个线程或进程的X集合的元素。这个集合的元素并无限止。

死锁的探测

讲了这么多,现在开始进入正题,讲述如何探测死锁。死锁探测的关键,就是上面的二个集合(X集合、Y集合)。

现有假设有这么三个线程abc。同时有资源r1r2r3r4......。现在假设线程abc分别拥有r1r2r3(这三个线程还有拥有其它资源,以......代替),可得到三个线程的X集合为:

Xa={r1......}

Xb={r2......}

Xc={r3...... }

此时,如果三个线程分别需要获取r3r1r2,则可得到三个线程的Y集合分别为:

Ya={r3}

Yb={r1}

Yc={r2}

此时会出现什么情况?死锁!三个线程分别拥有别人想拥有的东西而不能释放,这就形成了三个线程的死锁。下面,我将会论述如何找到死锁,以及死锁应该是什么形态的。

假设a集合最后一个去申请r3的锁,r3aY集合中(Ya)。r3所属的X集合是Xc.

找到Xc对应的Yc集合。发现其中有对象r2。找到r2所属的X集合Xb

找到Xb对应的Yb集合,发现其中有对象r1。找到r1所属的X集合Xa

找到Xa对应的Yc集合。

怎么样,看出些什么时候了?对,转了一圈有回来了——Ya->Xc->Yc->Xb->Yb->Xa->Ya。在点像苯的化学式吧。实际这是三个对象死锁的情况,实际n个对象死锁的情况也是类似的。下面,以偶对的方式给出“待锁定链”(Y链)的定义、待锁定环(Y环)的定义、死锁的定义。

待锁定链(Y链)、待锁定环(Y环)

有集合O与集合R。应用中的所有进程或线程属于集合O。应用中的所有资源属于集合ROiRj分别代表集合O与集合R中的对象。

当某个进程或线程成功锁定某个资源时,我们可以认为集合O与集合R中的相应元素形成偶对<Oi,Rj>。由一系列这样的偶对,可以组成一个锁定关系集合X

当某个进程或线程待锁定某个资源时,集合O与集合R中的相应元素也形成偶对<Ox,Ry>。由一系列这样的偶对,可以组成一个待锁定关系集合Y

“待锁定链”是一个图,而且是一个有向图。下面的规则是待锁定链的形成规则,也是待锁定链的定义。这个形成规则(或者说定义)是递归的。当集合O中的对象Oa将要锁定集合R中的对象Ra时,会形成偶对<Oa,Ra>。如果锁定成功,这个偶对<Oa,Ra>将会属于集合X而无法形成“待锁定链”。如果Ra被别的线程或进程锁定,<Oa,Ra>就会落入到集合Y中。以下是查找或形成待锁定链的步骤:

1、            首先,以偶对<Oa,Ra>为图的第一顶点(起点)

2、            从集合X中找到含Ra的偶对<Ob,Ra>。由于任意时刻Ra只能属于一个进程或线程,故集合X中,含Ra的偶对必是唯一的。

3、            在集合Y中找到含Ob的偶对<Ob,Rb>。通过上面的分析,我们知道任意时刻Ob只能拥有一个待锁定对象,故集合Y中,含Ob的偶对必是唯一的。

4、            <Ob,Rb>为图的第二个顶点,图由第一个顶点指向第二个顶点,形成如下的图形
<Oa,Ra>
>  <Ob,Rb>

5、            <Ob,Rb>为新的起点,重复上面的步骤1-4。要结束上面的递归,有两个结束条件。
a
、直到找到Y集合中的某个偶对<On,Rn>,该偶对具有如下的性质——元素RnX集合中有对应偶对<On+1,Rn>,On+1Y集合中无相应的偶对。最终形成的样子是:



b
、偶对<Oa,Ra>在图中又出现了,即从<Oa,Ra>出发双回到了<Oa,Ra>。最终形成的样子是:

如果整个递归过程是以A条件结束的,那么形成的就是待锁定链(Y链)。如果整个递归过程是以B条件结束的,那么形成的就是待锁定环(Y环)

死锁(真死锁、假死锁)的定义

如果一个线程或进程O,在锁定某项资源R时,通过上述规则,查找到了一个(实际上最多也只可能形成一个)待锁定环。那么,我就称这个线程或进程O在资源R上形成真死锁

真死锁,是由于上述的逻辑上的互锁循环而形成的。从图像上看,待锁定环是不是很像苯的化学式。从一定意义上来说,真死锁状态,可以说是程序的处在稳态(静态),而程序在没有形成真死锁时,可以说是处在动态。

实际上,还存在着一种假死锁。那会什么是假死锁?通俗一点讲,就是线程或进程锁定了一个资源后,长时间的拥有而不释放,这就是假死锁。就是那种形成了待锁定链,而未形成待锁定环,锁定链中的某个资源的RxX集合中拥有长期稳定的偶对<Ox,Rx>,我称这种关系为RxOx假死锁

想探测真死锁,利用上面的Y环查找算法(定义)就可以找到,如何去处理假死锁,我以后会描述。真死锁,我们可以自行开发程序来发现并处理。但对于假死锁,可能就需要编程语言方面进行改进了。

实用的待锁定环死锁探测应用必须要实现的功能

如果真的要实现上述的死锁探测算法,并有效的使用到工程实践中去,必须要实现以下的功能:

Ø         必须有一个“数据库”,记录哪些进程或线程锁定了哪些资源。同时,记录哪些资源被哪些进程或线程所期待(资源被别人锁定,但自己也想锁定)

Ø         必须有一种回调机制,当某个资源被释放时,能够及时通知下一个期待的进程或线程去拥有它并继续运行。

 

 

 

 

 

 

 

严家俊                     

2010125星期一   于家中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值