理论教育 线程死锁问题解决-Java程序设计

线程死锁问题解决-Java程序设计

时间:2023-10-18 理论教育 版权反馈
【摘要】:在前一小节介绍了线程的同步机制,使用synchronized关键字可以锁定某个对象,让其他线程无法获得这个对象锁而进入阻塞状态。两个线程都需要资源A和资源B,且两个线程分别锁定其中一个资源,这样两个线程就会相互等待对方的资源且会一直等待下去,从而造成线程死锁。图12.20程序运行结果从图12.20的运行结果可以看出,两个线程处于阻塞状态,没有办法继续执行,从而造成了死锁。

线程死锁问题解决-Java程序设计

在前一小节介绍了线程的同步机制,使用synchronized关键字可以锁定某个对象,让其他线程无法获得这个对象锁而进入阻塞状态。这种方法虽然可以避免多个线程同时访问某个共享资源,但是却可能产生一个新的问题—— 线程死锁。

线程死锁(DeadLock)是指两个或两个以上的线程互相持有对方所需要的资源,由于synchronized的特性,一个线程持有一个资源(对这个资源附加了锁),那么在该线程释放这个锁之前,其他线程将无法获得这个资源。假设当前线程不仅需要资源A(已经被当前线程锁定),还需要另外一个资源B才能执行,资源B在这个时候却被其他线程持有(被其他线程锁定),而其他线程不仅需要资源B,也需要资源A才能执行。两个线程都需要资源A和资源B,且两个线程分别锁定其中一个资源,这样两个线程就会相互等待对方的资源且会一直等待下去,从而造成线程死锁。

从上面的例子可以看出,线程的死锁其实是需要一些必要条件的,包括:

(1)互斥条件:一个资源只能被一个线程所占用,当一个线程获取到这个资源的锁之后,其他线程在该线程释放这个锁之前无法获得该资源。

(2)占有且不放弃:一个线程如果需要多个资源才能执行,那么在获取到部分资源后,将无休止的等待其他资源,这个等待过程没有时限,在等待过程中不放弃已经拥有的资源。

(3)不可剥夺条件:任何一个线程都无法强制获取别的线程已经占有的资源,即无法强制让其他线程解锁

(4)循环等待条件:存在至少一种资源的循环等待环路,环中每一个线程所占有的资源是环中下一个线程所请求的资源,如线程A拿着线程B的资源,线程B拿着线程A的资源,线程A和线程B构成一个循环等待环路。

【例12.12】中国人和美国人一起就餐,但是中国人得到是刀叉,美国人得到的是筷子,两个人都想获得对方的餐具先吃,这就造成了死锁,谁也没法吃饭。

在cn.pzhu.syn包下创建一个名为Example03的类,在这个类中通过中国人和美国人抢占资源来模拟死锁,关键代码如下:(www.daowen.com)

在上述代码中,DeadLockThread类的run()方法默认如果是“中国人”则默认获得“刀叉”,并开始不停地请求“筷子”;如果是“美国人”则默认获得“筷子”,并开始不停地请求“刀叉”。如果其中任何一人获得了餐具就“开始吃饭”,然后释放所拥有的资源。

程序运行结果如图12.20所示。

图12.20 程序运行结果

从图12.20的运行结果可以看出,两个线程处于阻塞状态,没有办法继续执行,从而造成了死锁。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈