您的位置:首页 > 其它

多线程死锁问题

2017-07-26 12:18 148 查看
一、死锁的概念

       多线程以及多进程改善了系统资源的利用率并提高了系统 的处理能力。然而,并发执行也带来了新的问题——死锁。所谓死锁是指多个线程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。

下面我们通过一些实例来说明死锁现象。

先看生活中的一个实例,2个人一起吃饭但是只有一双筷子,2人轮流吃(同时拥有2只筷子才能吃)。某一个时候,一个拿了左筷子,一人拿了右筷子,2个人都同时占用一个资源,等待另一个资源,这个时候甲在等待乙吃完并释放它占有的筷子,同理,乙也在等待甲吃完并释放它占有的筷子,这样就陷入了一个死循环,谁也无法继续吃饭。。。
在计算机系统中也存在类似的情况。例如,某计算机系统中只有一台打印机和一台输入 设备,进程P1正占用输入设备,同时又提出使用打印机的请求,但此时打印机正被进程P2 所占用,而P2在未释放打印机之前,又提出请求使用正被P1占用着的输入设备。这样两个进程相互无休止地等待下去,均无法继续执行,此时两个进程陷入死锁状态

二、产生死锁的条件

(1)互斥条件。即某个资源在一段时间内只能由一个进程或者线程占有,不能同时被两个或者两个以上的进程占有。这种独占资源如CD-ROM驱动器,打印机等,必须在占有该资源的进程或者线程主动释放它之后,其他进程或者线程才能只有该资源。这是由资源本身属性所决定的。如独木桥就是一种独占资源,两方的人不能同时过桥。

(2)不可抢占条件。进程或线程所获得的资源在未使用完毕之前,资源申请者不能强行地从资源占有者手中夺取资源,而只能由该资源的占有者自行释放。如过独木桥的人不能强迫对方后退,也不能非法地将对方推下桥,必须是桥上的人自己过桥后空出桥面(即主动释放占有资源),对方的人才能过桥。

(3)占有且申请条件。进程或线程至少已经占有一个资源,但又申请新的资源;由于该资源已被另外进程或者线程所占有,此时该进程或者线程会被阻塞;但是,它在等待新资源之时,仍继续占有已占有的资源。

(4)循环等待条件。存在一个进程或线程等待序列{P1,P2,....,P3},其中P1等待P2所占有的某一资源,P2等待P3所占有的某一资源,.......,而Pn又等待P1所占有的资源,形成一个循环等待环。

PS:上面所提到的四个条件在死锁发生时会同时发生。也就是说,只要有一个必要条件不满足,则死锁就可以排除。

三、出现死锁的五种场景

(1)notify与notifyAll的使用。

如:


   两个生产者P1、P2,两个消费者C1、C2,共同操作一个队列,队列最大长度为1。

开始P1、P2、C1、C2都处于运行状态(RUNNABLE)。

C1先获得锁,P1、P2、C2为BLOCKED状态。C1发现队列为空,主动进入WAITING。C2接着获得锁,成为RUNNABLE状态,发现队列为空,主动进入WAITING。

P1接着获得锁,成为RUNNABLE状态,在队列中插入一个元素,notify到了另一个生产者P2。P1循环生产,发现队列不为空,成为WAITING。

P2成为RUNNABLE状态,发现队列有值,主动进入WAITING。

此时锁已被释放,但P1、P2、C1、C2都处于WAITING状态,没有线程去获取锁,死了。
        (2)同一个线程拥有有多把锁

如:


(3)使用循环

        如:


thread1首先执行,加锁,while(!condition)为永真持续循环,此时thread2等待thread1解锁从而获取锁,thread1等待thread2将condition置为true,跳出循环解锁,这就构成了死锁。

(4)thread.suspend()和thread.stop()

         当挂起或者停止一个拥有某一把锁的线程时,该线程并不会释放锁,这就容易造成死锁。

(5)哲学家就餐问题

5个哲学家,5跟筷子,哲学家必须用两只筷子吃东西,若5个人同时拿起自己左边(右边)的筷子会将构成死锁。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: