Java——面試題:寫出一個死鎖的實例(三種情況分析死鎖形成原因)

面試題:

寫出一個死鎖的實例。

 

 

Java發生死鎖的根本原因是:

死鎖是因爲多線程訪問共享資源,由於訪問的順序不當所造成的,在申請鎖時發生了交叉閉環申請。即線程在獲得了鎖A並且沒有釋放的情況下去申請鎖B,這時,另一個線程已經獲得了鎖B,在釋放鎖B之前又要先獲得鎖A,因此閉環發生,陷入死鎖循環。

 

 

 

實例1:

在MyLock類中定義兩個不同的靜態鎖對象。

package com.deadLock;

class MyLock{
    static Object locka = new Object(); //注意此處必須時static,
    static Object lockb = new Object(); //不僅能類名訪問,也是讓不同線程訪問共享數據
}

class Lock implements Runnable{
    private boolean flag;

    public Lock(boolean flag) {
        this.flag = flag;
    }

    @Override
    public void run() {
        if (flag){
            while(true){
               deadLockab();
            }
        }else{
            while(true){
                deadLockba();
            }
        }
    }

    private void deadLockab() {
        String name = Thread.currentThread().getName();
        synchronized (MyLock.locka){
            System.out.println(name+"...lock on "+MyLock.locka);
            synchronized (MyLock.lockb){
                System.out.println(name+"...lock on "+MyLock.lockb);
            }
        }
    }

    private void deadLockba() {
        String name = Thread.currentThread().getName();
        synchronized (MyLock.lockb){
            System.out.println(name+"...lock on "+MyLock.lockb);
            synchronized (MyLock.locka){
                System.out.println(name+"...lock on "+MyLock.locka);
            }
        }
    }

}

public class DeadLockDemo2 {
    public static void main(String[] args) {
        Thread t1 = new Thread(new Lock(true));
        Thread t2 = new Thread(new Lock(false));
        t1.start();
        t2.start();
    }
}

運行結果(形成死鎖):

 

實例2(無法形成死鎖):

在實現Runnable類中定義兩個不同的鎖,注意兩個線程任務不同,所以這兩個鎖並不是默認靜態鎖。

package com.deadLock;


class Lock implements Runnable{
    private boolean flag;
    private Object obj1 = new Object();
    private Object obj2 = new Object();
    public Lock(boolean flag) {
        this.flag = flag;
    }

    @Override
    public void run() {
        if (flag){
            while(true){
               deadLockab();
            }
        }else{
            while(true){
                deadLockba();
            }
        }
    }

    private void deadLockab() {
        String name = Thread.currentThread().getName();
        synchronized (obj1){
            System.out.println(name+"...lock on "+obj1);
            synchronized (obj2){
                System.out.println(name+"...lock on "+obj2);
            }
        }
    }

    private void deadLockba() {
        String name = Thread.currentThread().getName();
        synchronized (obj2){
            System.out.println(name+"...lock on "+obj2);
            synchronized (obj1){
                System.out.println(name+"...lock on "+obj1);
            }
        }
    }

}

public class DeadLockDemo2 {
    public static void main(String[] args) {
        Thread t1 = new Thread(new Lock(true));
        Thread t2 = new Thread(new Lock(false));
        t1.start();
        t2.start();
    }
}

運行結果:

 

實例3(實例2改進,形成死鎖):

在實現Runnable類中定義兩個不同的鎖,並且兩個線程任務不同,兩個鎖必須手動聲明爲靜態鎖。

package com.notdeadlock;


class Lock implements Runnable{
    private boolean flag;
    private static Object obj1 = new Object();
    private static Object obj2 = new Object();
    public Lock(boolean flag) {
        this.flag = flag;
    }

    @Override
    public void run() {
        if (flag){
            while(true){
                deadLockab();
            }
        }else{
            while(true){
                deadLockba();
            }
        }
    }

    private void deadLockab() {
        String name = Thread.currentThread().getName();
        synchronized (obj1){
            System.out.println(name+"...lock on "+obj1);
            synchronized (obj2){
                System.out.println(name+"...lock on "+obj2);
            }
        }
    }

    private void deadLockba() {
        String name = Thread.currentThread().getName();
        synchronized (obj2){
            System.out.println(name+"...lock on "+obj2);
            synchronized (obj1){
                System.out.println(name+"...lock on "+obj1);
            }
        }
    }

}

public class NotDeadLock{
    public static void main(String[] args) {
        Thread t1 = new Thread(new Lock(true));
        Thread t2 = new Thread(new Lock(false));
        t1.start();
        t2.start();
    }
}

 運行結果:

 

實例4(形成死鎖(2個線程)):

package com.deadlock3;

class Lock implements Runnable{
    private Object obj1; //注意此處不能爲final/static
    private Object obj2;
    //如果final就不能在下面構造方法中重新賦值;如果static所有線程共享鎖,線程t1,t2都在使用obj2這把鎖,無法形成死鎖。

    public Lock(Object obj1, Object obj2) {
        this.obj1 = obj1;
        this.obj2 = obj2;
    }

    @Override
    public void run() {
        while(true){
                deadLock();
        }
    }


    private void deadLock() {
        String name = Thread.currentThread().getName();
        synchronized (obj1){
            System.out.println(name+"...lock on "+obj1);
            synchronized (obj2){
                System.out.println(name+"...lock on "+obj2);
            }
        }
    }
}

public class DeadLockDemo3 {
    public static void main(String[] args) {
        Object obj1 = new Object();
        Object obj2 = new Object();
        Thread t1 = new Thread(new Lock(obj1, obj2));
        Thread t2 = new Thread(new Lock(obj2, obj1));
        t1.start();
        t2.start();
    }
}

運行結果:

 

實例5(形成死鎖(3個線程)):

package com.deadlock3;

class Lock implements Runnable{
    private Object obj1; //注意此處不能爲final/static
    private Object obj2; 
    //如果final就不能在下面構造方法中重新賦值;如果static所有線程共享鎖,最後只有兩把鎖,無法鎖住所有線程。

    public Lock(Object obj1, Object obj2) {
        this.obj1 = obj1;
        this.obj2 = obj2;
    }

    @Override
    public void run() {
        while(true){
                deadLock();
        }
    }


    private void deadLock() {
        String name = Thread.currentThread().getName();
        synchronized (obj1){
            System.out.println(name+"...lock on "+obj1);
            synchronized (obj2){
                System.out.println(name+"...lock on "+obj2);
            }
        }
    }
}

public class DeadLockDemo3 {
    public static void main(String[] args) {
        Object obj1 = new Object();
        Object obj2 = new Object();
        Object obj3 = new Object();
        Thread t1 = new Thread(new Lock(obj1, obj2));
        Thread t2 = new Thread(new Lock(obj2, obj3));
        Thread t3 = new Thread(new Lock(obj3, obj1));
        t1.start();
        t2.start();
        t3.start();
    }
}

 運行結果:

 

 

總結:

推薦使用實例4這種方法形成死鎖,代碼簡單,理解起來也很方便,如果有什麼問題,歡迎一起探討。 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章