理解死锁的概念(实例)

 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对象加锁,两个线程互相等待对方先释放,出现死锁现象。

posted @ 2019-11-13 11:02  什么能让我为谁停留  阅读(395)  评论(0编辑  收藏  举报