理解死锁的概念(实例)
1 package com.lijunwei.nov13; 2 3 public class A { 4 public synchronized void foo(B b) { 5 System.out.println("当前线程名:" + Thread.currentThread().getName() + " 进入了A实例的foo()方法"); // ① 6 try { 7 Thread.sleep(200); 8 } catch (InterruptedException e) { 9 e.printStackTrace(); 10 } 11 12 System.out.println("当前线程名:" + Thread.currentThread().getName()+" 企图调用B实例的last()方法"); // ③ 13 b.last(); 14 } 15 16 public synchronized void last() { 17 System.out.println("进入了A实例的last()方法"); 18 } 19 20 21 }
1 package com.lijunwei.nov13; 2 3 public class B { 4 5 public synchronized void bar(A a) { 6 System.out.println("当前线程名:" + Thread.currentThread().getName() + " 进入了B实例的bar()方法"); // ② 7 try { 8 Thread.sleep(200); 9 } catch (InterruptedException e) { 10 e.printStackTrace(); 11 } 12 13 System.out.println("当前线程名:" + Thread.currentThread().getName()+" 企图调用A实例的last()方法"); // ④ 14 a.last(); 15 } 16 17 public synchronized void last() { 18 System.out.println("进入了B实例的last()方法"); 19 } 20 21 22 }
package com.lijunwei.nov13; public class DeadLockTest implements Runnable { private A a = new A(); private B b = new B(); public void init() { Thread.currentThread().setName("Main Thread..."); // 调用a对象的foo()方法 a.foo(b); System.out.println("进入了主线程之后..."); } @Override public void run() { Thread.currentThread().setName("Sub Thread..."); // 调用b对象的bar()方法 b.bar(a); System.out.println("进入了副线程后"); } public static void main(String[] args) { // main thread DeadLockTest deadLockTest = new DeadLockTest(); // sub thread new Thread(deadLockTest).start(); deadLockTest.init(); } }
ref:疯狂java讲义第五版 p757
死锁产生过程的分析:
程序中A、B对象的方法都是同步方法,也就是说A对象和B对象都是同步锁。程序中有两个线程执行副线程的线程执行体是DeadLockTest里的main()方法(main方法调用了init方法)。其中run方法中让B对象调用bar()方法,init()方法让A对象调用foo()方法。图中显示先执行了init()方法,调用了A对象的foo()方法,进入foo()方法前该线程对A对象加锁——当程序执行到①代码时,主线程暂停了200ms;CPU切换至另一个线程,注意sleep方法并不会释放锁另一个线程让B对象执行bar()方法,所以看到副线程开始执行B对象的bar()方法,进入bar()方法之前该线程对B对象加锁——当程序执行到②时,副线程也暂停200ms;接下来主线程会先醒过来,继续向下执行。直到③处代码需要调用B对象的last()方法——执行该方法需要对B对象加锁,而此时副线程持有B对象的锁,因此主线程被阻塞;接下来副线程也醒过来了并继续向下执行,知道④处需要调用A对象的last()方法——执行该方法需要对A对象加锁,而此时主线程持有A对象的锁,因此副线程被阻塞。至此,就出现了主线程保持着A对象的锁,等待对B对象加锁,副线程保持着B对象的锁,等待对A对象加锁,两个线程互相等待对方先释放,出现死锁现象。