一种特殊类型的错误,需要避免对多任务具体涉及死锁,当两个线程有一个循环依赖于一对同步对象时发生。
例如,假设一个线程进入监视器对象X和其他线程进入监视器对象Y。如果在X中的线程试图调用Y上的任何synchronized方法,它会阻止预期。但是,如果在Y中的线程,反过来,尝试调用X上的任何synchronized方法,该线程将永远等待,因为访问的X,那就要释放自己的Y上的锁,使第一个线程可以完成。
例子:
要充分认识死锁看到它的实际是有用的。下一个示例创建两个类,A和B,具有方法foo()和bar(),分别为,其试图在其他类调用一个方法之前稍作停顿。
主类,命名为死锁,创建一个A和一个B实例,然后启动第二个线程来设置死锁条件。foo()和bar()方法使用sleep()方法,以此来迫使死锁情况发生。
class A { synchronized void foo(B b) { String name = Thread.currentThread().getName(); System.out.println(name + " entered A.foo"); try { Thread.sleep(1000); } catch(Exception e) { System.out.println("A Interrupted"); } System.out.println(name + " trying to call B.last()"); b.last(); } synchronized void last() { System.out.println("Inside A.last"); } } class B { synchronized void bar(A a) { String name = Thread.currentThread().getName(); System.out.println(name + " entered B.bar"); try { Thread.sleep(1000); } catch(Exception e) { System.out.println("B Interrupted"); } System.out.println(name + " trying to call A.last()"); a.last(); } synchronized void last() { System.out.println("Inside A.last"); } } public class Deadlock implements Runnable { A a = new A(); B b = new B(); Deadlock() { Thread.currentThread().setName("MainThread"); Thread t = new Thread(this, "RacingThread"); t.start(); a.foo(b); // get lock on a in this thread. System.out.println("Back in main thread"); } public void run() { b.bar(a); // get lock on b in other thread. System.out.println("Back in other thread"); } public static void main(String args[]) { new Deadlock(); } }
下面是该程序的一些输出:
MainThread entered A.fooRacingThread entered B.barMainThread trying to call B.last()RacingThread trying to call A.last()因为程序已经死锁时需要按Ctrl-C来结束程序。可以看到一个完整的线程,并通过按PC上的CTRL-BREAK监视缓存转储。
会看到RacingThread持有B上监视器,而它正在等待a监视器上。与此同时,MainThread拥有并正在等待获取湾这个程序将永远不会完成。
这个例子说明,如果多线程程序锁定偶然,死锁应该检查的首要条件之一。
顺序锁:
一个常见的线程伎俩来避免死锁是顺序锁。通过顺序锁,它给线程特定顺序获得多个锁。
死锁例子:
下面是一个死锁的描述:
这将产生以下结果:
Creating two bank accounts... Creating two teller threads... Starting both threads... Transferring from 101 to 102 Transferring from 102 to 101 Withdrawing from 101 Depositing into 102 Withdrawing from 102 Depositing into 101