死鎖詳解

死鎖實(shí)現(xiàn)

public class DeathLockTest {

    static Integer b = 100;
    static Integer a = 0;
    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (a){
                System.out.println(Thread.currentThread().getName() + ": i locked a");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (b){
                    System.out.println(Thread.currentThread().getName() + ": i locked b");
                }
            }
        },"thread-a").start();
        new Thread(() -> {
            synchronized (b){
                System.out.println(Thread.currentThread().getName() + ": i locked b");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (a){
                    System.out.println(Thread.currentThread().getName() + ": i locked a");
                }
            }
        },"thread-b").start();
    }
}
死鎖結(jié)果

這里簡單的用了兩個線程去分別獲取到a的鎖和b的鎖,然后再獲取另外一個鎖的時候,就發(fā)現(xiàn)互相等待,互相不會釋放資源,導(dǎo)致死鎖的發(fā)生。死鎖在我們的項目中會導(dǎo)致很嚴(yán)重的后果,有多嚴(yán)重,碰到的人知道。

定義

死鎖是指兩個或兩個以上的進(jìn)程在執(zhí)行過程中,由于競爭資源或者由于彼此通信而造成的一種阻塞的現(xiàn)象,若無外力作用,它們都將無法推進(jìn)下去。此時稱系統(tǒng)處于死鎖狀態(tài)或系統(tǒng)產(chǎn)生了死鎖,這些永遠(yuǎn)在互相等待的進(jìn)程稱為死鎖進(jìn)程。[百度百科]

如何避免

1:獲取鎖的順序問題
如果我們在獲取兩個資源的時候,獲取的順序相同,都先獲取到a的鎖,然后再獲取到b的鎖,則在上述例子中避免了死鎖。
2:避免同時持有兩個資源的鎖
假設(shè)上面的例子中,thread-a獲取到a的鎖以后,對a的操作進(jìn)行完成以后再獲取b的鎖,那么,就可以解開這個死鎖,thread-b同理。
3:使用java.util.concurrent包中的相關(guān)方法改造
對上面的代碼進(jìn)行改造

public class DeathLockTest2 {
    
    static Integer a = 0;
    static Integer b = 100;

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

    public static void main(String[] args) {
        new Thread(()->{
            try{
                if(lock1.tryLock()){
                    System.out.println(Thread.currentThread().getName() + ": lock1 was locked");
                    a++;
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if(lock2.tryLock()){
                        System.out.println(Thread.currentThread().getName()+ " lock2 was locked");
                        b--;
                    }
                    System.out.println(Thread.currentThread().getName()+ "--> ++a :" + a + " ,  --b:" + b);
                }
            }finally {
                    lock1.unlock();
                    lock2.unlock();
            }
        },"thread-a").start();
        new Thread(()->{
            try {
                if(lock2.tryLock()){
                    System.out.println(Thread.currentThread().getName()+ " lock2 was locked");
                    b--;
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if(lock1.tryLock()){
                        System.out.println(Thread.currentThread().getName() + ": lock1 was locked");
                        a++;
                    }
                }
                System.out.println(Thread.currentThread().getName()+ "--> ++a :" + a + " ,  --b:" + b);
            }finally {
                lock2.unlock();
                lock1.unlock();
            }
        },"thread-b").start();
        //定時器計時
        new Timer().schedule(new TimerTask(){
            @Override
            public void run() {
                System.out.println(String.valueOf(Calendar.getInstance().get(Calendar.SECOND)));
            }
        }, 1, 1000);
    }
}

使用java.util.concurrent.locks.Lock.tryLock()方法,結(jié)果如下:

解鎖

程序在等待了5s左右的時候,線程自動結(jié)束運(yùn)行了,使用這種方式則不會使我們的線程出現(xiàn)完全死鎖,程序無法進(jìn)行的狀態(tài),在等待一定時間后,線程無法獲取到鎖,則自動放棄獲取鎖。

結(jié)束語:可能還有更好的解決辦法,歡迎大家留言指正探討,謝謝!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • http://www.itdecent.cn/p/f343782f19fc 背景 10月2號凌晨12:08收到報警...
    吃番茄的土撥鼠閱讀 1,722評論 2 4
  • 進(jìn)程和線程 進(jìn)程 所有運(yùn)行中的任務(wù)通常對應(yīng)一個進(jìn)程,當(dāng)一個程序進(jìn)入內(nèi)存運(yùn)行時,即變成一個進(jìn)程.進(jìn)程是處于運(yùn)行過程中...
    勝浩_ae28閱讀 5,259評論 0 23
  • Java8張圖 11、字符串不變性 12、equals()方法、hashCode()方法的區(qū)別 13、...
    Miley_MOJIE閱讀 3,906評論 0 11
  • 一、寫作的定義 什么是寫作?百度百科里說:寫作是運(yùn)用語言文字符號反映客觀事物、表達(dá)思想感情、傳遞知識信息的創(chuàng)造性腦...
    愛笑的藍(lán)胖閱讀 975評論 11 21
  • 打卡第八天 起床:6.15 就寢:24:00 天氣:晴 心情:好 紀(jì)念日:沒有 任務(wù)清單 改進(jìn):沒有按時按計劃完成...
    笑云昵閱讀 209評論 0 0

友情鏈接更多精彩內(nèi)容