面試被問到,Java如何避免死鎖?引發的思考。

模擬死鎖:

/**
 * Create by LiXiaoTian 2020/5/10 11:34
 * 死鎖問題
 */
public class Deadlock {

    public static String resource1 = "resource1";
    public static String resource2 = "resource2";
    public static void main(String[] args) {
        Thread thread1 = new Thread(new BusinessA());
        Thread thread2 = new Thread(new BusinessB());
        thread1.setName("線程1");
        thread2.setName("線程2");
        thread1.start();
        thread2.start();
    }
    static class BusinessA implements Runnable {
        @Override
        public void run() {
            try{
                System.out.println("BusinessA啓動");
                while(true){
                    synchronized(Deadlock.resource1){
                        System.out.println("BusinessA拿到了resource1的鎖");
                        Thread.sleep(3000);//獲取resource1後先等一會兒,讓BusinessB有足夠的時間鎖住resource2
                        System.out.println("BusinessA想拿resource2的鎖。。。。");
                        synchronized(Deadlock.resource2){
                            System.out.println("BusinessA獲得到了resource2的鎖");
                        }
                    }
                }
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
    static class BusinessB implements Runnable {
        @Override
        public void run(){
            try{
                System.out.println("BusinessB啓動");
                while(true){
                    synchronized(Deadlock.resource2){
                        System.out.println("BusinessB拿得到了resource2的鎖");
                        Thread.sleep(3000);//獲取resource2後先等一會兒,讓BusinessA有足夠的時間鎖住resource1
                        System.out.println("BusinessB想拿resource1的鎖。。。。");
                        synchronized(Deadlock.resource1){
                            System.out.println("BusinessB獲得到了resource1的鎖");
                        }
                    }
                }
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }

}

 

 

如何解決死鎖呢?

解決方法:

1、線程因某個條件爲未滿足而受阻,不能讓其繼續佔有資源,也就是說,讓進入阻塞狀態的線程釋放所有資源。

2、如果有多個對象需要互斥訪問,應該確定線程獲得鎖的順序,並保證整個程序以相反的順序釋放鎖。也就是說,一個線程獲得一個資源的鎖之後,不能再佔用其他對象資源的鎖,釋放資源鎖的順序:先被佔有的資源的鎖後釋放。

/**
 * Create by LiXiaoTian 2020/5/10 11:34
 * 解決死鎖問題
 */
public class Deadlock {

    public static ReentrantLock lock1 = new ReentrantLock();
    public static ReentrantLock lock2 = new ReentrantLock();

    public static String resource1 = "resource1";
    public static String resource2 = "resource2";

    public static void main(String[] args) {
        Thread thread1 = new Thread(new BusinessA());
        Thread thread2 = new Thread(new BusinessB());
        thread1.setName("線程1");
        thread2.setName("線程2");
        thread1.start();
        thread2.start();
    }

    static class BusinessA implements Runnable {
        boolean flag = true;

        @Override
        public void run() {
            try {
                System.out.println("線程1啓動");
                while (flag) {
                    Thread.sleep(1000);
                    if (Deadlock.lock1.tryLock(1, TimeUnit.SECONDS)) {
                        System.out.println("線程1已鎖住lock1");
                        Thread.sleep(5000);
                        if (Deadlock.lock2.tryLock(1, TimeUnit.SECONDS)) {
                            System.out.println("線程1已鎖住lock2");
                            flag = false;
                        } else {
                            System.out.println("線程1鎖失敗lock2");
                        }
                    } else {
                        System.out.println("線程1鎖失敗lock1");
                    }
                    System.out.println("當前線程===========================" + Thread.currentThread().getName());
                    //釋放鎖
                    if (lock1.isHeldByCurrentThread()) {
                        lock1.unlock();
                        System.out.println("線程1釋放lock1");
                    }
                    if (lock2.isHeldByCurrentThread()) {
                        lock2.unlock();
                        System.out.println("線程1釋放lock2");
                    }
                    Thread.sleep(2000);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    static class BusinessB implements Runnable {

        boolean flag = true;

        @Override
        public void run() {
            try {
                System.out.println("線程2啓動");
                while (flag) {
                    if (Deadlock.lock1.tryLock(1, TimeUnit.SECONDS)) {
                        System.out.println("線程2已鎖住lock1");
                        Thread.sleep(6000);
                        if (Deadlock.lock2.tryLock(1, TimeUnit.SECONDS)) {
                            System.out.println("線程2已鎖住lock2");
                            flag = false;
                        } else {
                            System.out.println("線程2鎖失敗lock2");
                        }
                    } else {
                        System.out.println("線程2鎖失敗lock1");
                    }
                    System.out.println("當前線程===========================" + Thread.currentThread().getName());
                    //釋放鎖
                    if (lock1.isHeldByCurrentThread()) {
                        lock1.unlock();
                        System.out.println("線程2釋放lock1");
                    }
                    if (lock2.isHeldByCurrentThread()) {
                        lock2.unlock();
                        System.out.println("線程2釋放lock2");
                    }

                }
                Thread.sleep(2000);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

 

 

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