成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

(十四)java多線(xiàn)程之死鎖以及解決方案

wendux / 903人閱讀

摘要:本人郵箱歡迎轉(zhuǎn)載轉(zhuǎn)載請(qǐng)注明網(wǎng)址代碼已經(jīng)全部托管有需要的同學(xué)自行下載引言多線(xiàn)程如果設(shè)計(jì)的不合理的話(huà)很可能就會(huì)出現(xiàn)死鎖當(dāng)兩個(gè)或者多個(gè)線(xiàn)程同事想要去獲取共享資源的鎖時(shí)但每個(gè)線(xiàn)程都要等其他線(xiàn)程把他們各自的鎖給釋放才能繼續(xù)運(yùn)行這就是死鎖出現(xiàn)死鎖必須具

本人郵箱:
歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明網(wǎng)址 http://blog.csdn.net/tianshi_kco
github: https://github.com/kco1989/kco
代碼已經(jīng)全部托管github有需要的同學(xué)自行下載

引言

多線(xiàn)程如果設(shè)計(jì)的不合理的話(huà),很可能就會(huì)出現(xiàn)死鎖.當(dāng)兩個(gè)或者多個(gè)線(xiàn)程同事想要去獲取共享資源的鎖時(shí),但每個(gè)線(xiàn)程都要等其他線(xiàn)程把他們各自的鎖給釋放,才能繼續(xù)運(yùn)行,這就是死鎖.出現(xiàn)死鎖必須具備以下幾點(diǎn)

要有兩個(gè)或兩個(gè)以上的線(xiàn)程

至少有兩個(gè)共享資源的鎖

至少存在兩個(gè)線(xiàn)程各自擁有一個(gè)鎖

現(xiàn)在這兩個(gè)線(xiàn)程在等待獲取彼此的鎖,這就出現(xiàn)死鎖了

比如Thread1

synchronized(A){
    //Thread1 執(zhí)行到這里
    synchronized(B){
    ...
    }
}

Thread2

synchronized(B){
    //Thread2 執(zhí)行到這里
    synchronized(A){
    ...
    }
}

以上這種情況就是死鎖,如果是兩個(gè)線(xiàn)程出現(xiàn)死鎖,問(wèn)題可能還比較好找.更復(fù)雜是有多個(gè)線(xiàn)程,比如線(xiàn)程n各自擁有鎖n,然后線(xiàn)程1線(xiàn)程n-1,正在請(qǐng)求獲取鎖n+1,而線(xiàn)程n正在請(qǐng)求獲取鎖1,這樣也或出現(xiàn)死鎖,而且還更難被發(fā)現(xiàn).

例子

我們要看一個(gè)例子

public class Demo1 {
    public static void main(String[] args) {
        Object bigGate = new Object();
        Object smallGate = new Object();
        new Thread(new Runnable() {
            @Override
            public void run() {
                String name = Thread.currentThread().getName();
                synchronized (bigGate){
                    System.out.println(name + ":我把大門(mén)給鎖了...然后我休息一下...");
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(name + ":我現(xiàn)在要進(jìn)入小門(mén).....");
                    synchronized (smallGate){
                        System.out.println(name + ":我永遠(yuǎn)都進(jìn)不來(lái)啊.....");
                    }

                }
            }
        },"小明").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                String name = Thread.currentThread().getName();
                synchronized (smallGate){
                    System.out.println(name + ":我把小門(mén)給鎖了...然后我休息一下...");
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(name + ":我現(xiàn)在要進(jìn)入大門(mén).....");
                    synchronized (bigGate){
                        System.out.println(name + ":我永遠(yuǎn)都進(jìn)不來(lái)啊.....");
                    }

                }
            }
        },"小紅").start();
    }
}

運(yùn)行結(jié)果

小明我把大門(mén)給鎖了...然后我休息一下...
小紅我把小門(mén)給鎖了...然后我休息一下...
小明:我現(xiàn)在要進(jìn)入小門(mén).....
小紅:我現(xiàn)在要進(jìn)入大門(mén).....
//然后程序到這里就一直不動(dòng)了.....
解決辦法

鎖的順序,讓兩個(gè)線(xiàn)程獲取鎖的順序是一直,則不會(huì)出現(xiàn)死鎖

public class Demo2 {
    public static void main(String[] args) {
        Object bigGate = new Object();
        Object smallGate = new Object();
        new Thread(new Runnable() {
            @Override
            public void run() {
                String name = Thread.currentThread().getName();
                synchronized (bigGate){
                    System.out.println(name + ":我把大門(mén)給鎖了...然后我休息一下...");
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(name + ":我現(xiàn)在要進(jìn)入小門(mén).....");
                    synchronized (smallGate){
                        System.out.println(name + ":我終于進(jìn)來(lái)了.....");
                    }

                }
            }
        },"小明").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                String name = Thread.currentThread().getName();
                synchronized (bigGate){
                    System.out.println(name + ":我把大門(mén)給鎖了...然后我休息一下...");
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(name + ":我現(xiàn)在要進(jìn)入小門(mén).....");
                    synchronized (smallGate){
                        System.out.println(name + ":我終于進(jìn)來(lái)了.....");
                    }

                }
            }
        },"小紅").start();
    }
}

運(yùn)行結(jié)果:

小明:我把大門(mén)給鎖了...然后我休息一下...
小明:我現(xiàn)在要進(jìn)入小門(mén).....
小明:我終于進(jìn)來(lái)了.....
小紅:我把大門(mén)給鎖了...然后我休息一下...
小紅:我現(xiàn)在要進(jìn)入小門(mén).....
小紅:我終于進(jìn)來(lái)了.....

在獲取鎖的時(shí)候加超時(shí)時(shí)間,這里我們用之前學(xué)的Lock來(lái)做例子

public class Demo3 {
    public static void main(String[] args) {
        Lock bigGate = new ReentrantLock();
        Lock smallGate = new ReentrantLock();
        Random random = new Random();
        new Thread(new Runnable() {
            @Override
            public void run() {
                String name = Thread.currentThread().getName();
                bigGate.lock();
                try {
                    System.out.println(name + ":我把大門(mén)給鎖了...然后我休息一下...");
                    Thread.sleep(100);
                    System.out.println(name + ":我現(xiàn)在要進(jìn)入小門(mén).....");
                    if(smallGate.tryLock(random.nextInt(500), TimeUnit.MILLISECONDS)){
                        try {
                            System.out.println(name + ":我終于進(jìn)來(lái)了.....");
                        }finally {
                            smallGate.unlock();
                        }
                    }else{
                        System.out.println(name + ":我進(jìn)不去小門(mén),算了,不進(jìn)了...");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    bigGate.unlock();
                }
            }
        },"小明").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                String name = Thread.currentThread().getName();
                smallGate.lock();
                try {
                    System.out.println(name + ":我把小門(mén)給鎖了...然后我休息一下...");
                    Thread.sleep(100);
                    System.out.println(name + ":我現(xiàn)在要進(jìn)入大門(mén).....");
                    if(bigGate.tryLock(random.nextInt(500), TimeUnit.MILLISECONDS)){
                        try {
                            System.out.println(name + ":我終于進(jìn)來(lái)了.....");
                        }finally {
                            bigGate.unlock();
                        }
                    }else{
                        System.out.println(name + ":我進(jìn)不去大門(mén),算了,不進(jìn)了...");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    smallGate.unlock();
                }
            }
        },"小紅").start();
    }
}

運(yùn)行結(jié)果:

小明:我把大門(mén)給鎖了...然后我休息一下...
小紅:我把小門(mén)給鎖了...然后我休息一下...
小明:我現(xiàn)在要進(jìn)入小門(mén).....
小紅:我現(xiàn)在要進(jìn)入大門(mén).....
小紅:我進(jìn)不去大門(mén),算了,不進(jìn)了...
小明:我終于進(jìn)來(lái)了.....

這樣也可以保證不會(huì)出現(xiàn)死鎖.

打賞

如果覺(jué)得我的文章寫(xiě)的還過(guò)得去的話(huà),有錢(qián)就捧個(gè)錢(qián)場(chǎng),沒(méi)錢(qián)給我捧個(gè)人場(chǎng)(幫我點(diǎn)贊或推薦一下)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/67041.html

相關(guān)文章

  • 超詳細(xì)的Java面試題總結(jié)(二)Java基礎(chǔ)知識(shí)篇

    摘要:超詳細(xì)的面試題總結(jié)一之基本知識(shí)多線(xiàn)程和虛擬機(jī)創(chuàng)建線(xiàn)程有幾種不同的方式你喜歡哪一種為什么繼承類(lèi)實(shí)現(xiàn)接口應(yīng)用程序可以使用框架來(lái)創(chuàng)建線(xiàn)程池實(shí)現(xiàn)接口。死亡線(xiàn)程方法執(zhí)行結(jié)束,或者因異常退出了方法,則該線(xiàn)程結(jié)束生命周期。死亡的線(xiàn)程不可再次復(fù)生。 超詳細(xì)的Java面試題總結(jié)(一)之Java基本知識(shí) 多線(xiàn)程和Java虛擬機(jī) 創(chuàng)建線(xiàn)程有幾種不同的方式?你喜歡哪一種?為什么? 繼承Thread類(lèi) 實(shí)現(xiàn)R...

    wangjuntytl 評(píng)論0 收藏0
  • 我的阿里路+Java面經(jīng)考點(diǎn)

    摘要:我的是忙碌的一年,從年初備戰(zhàn)實(shí)習(xí)春招,年三十都在死磕源碼,三月份經(jīng)歷了阿里五次面試,四月順利收到實(shí)習(xí)。因?yàn)槲倚睦砗芮宄?,我的目?biāo)是阿里。所以在收到阿里之后的那晚,我重新規(guī)劃了接下來(lái)的學(xué)習(xí)計(jì)劃,將我的短期目標(biāo)更新成拿下阿里轉(zhuǎn)正。 我的2017是忙碌的一年,從年初備戰(zhàn)實(shí)習(xí)春招,年三十都在死磕JDK源碼,三月份經(jīng)歷了阿里五次面試,四月順利收到實(shí)習(xí)offer。然后五月懷著忐忑的心情開(kāi)始了螞蟻金...

    姘擱『 評(píng)論0 收藏0
  • 線(xiàn)程死鎖就是這么簡(jiǎn)單

    摘要:此時(shí)線(xiàn)程需要鎖才能繼續(xù)往下執(zhí)行。但是線(xiàn)程的鎖并沒(méi)有釋放,線(xiàn)程的鎖也沒(méi)有釋放。 前言 只有光頭才能變強(qiáng) 回顧前面: ThreadLocal就是這么簡(jiǎn)單 多線(xiàn)程三分鐘就可以入個(gè)門(mén)了! 多線(xiàn)程基礎(chǔ)必要知識(shí)點(diǎn)!看了學(xué)習(xí)多線(xiàn)程事半功倍 Java鎖機(jī)制了解一下 AQS簡(jiǎn)簡(jiǎn)單單過(guò)一遍 Lock鎖子類(lèi)了解一下 線(xiàn)程池你真不來(lái)了解一下嗎? 本篇主要是講解死鎖,這是我在多線(xiàn)程的最后一篇了。主要將多線(xiàn)程...

    winterdawn 評(píng)論0 收藏0
  • Java線(xiàn)程進(jìn)階(十四)—— J.U.Catomic框架:AtomicReference

    摘要:但是,有些操作會(huì)依賴(lài)于對(duì)象的變化過(guò)程,此時(shí)的解決思路一般就是使用版本號(hào)。在變量前面追加上版本號(hào),每次變量更新的時(shí)候把版本號(hào)加一,那么就會(huì)變成。四的引入就是上面所說(shuō)的加了版本號(hào)的。 showImg(https://segmentfault.com/img/remote/1460000016012188); 本文首發(fā)于一世流云的專(zhuān)欄:https://segmentfault.com/blo...

    aboutU 評(píng)論0 收藏0
  • Java基礎(chǔ)學(xué)習(xí)——線(xiàn)程線(xiàn)程間通信(安全問(wèn)題、等待喚醒機(jī)制)

    摘要:線(xiàn)程間通信其實(shí)就是多個(gè)線(xiàn)程操作同一個(gè)資源,但動(dòng)作不同。同步前提是多線(xiàn)程。將該線(xiàn)程載入線(xiàn)程池,等待喚醒。該方法拋出異常,故需要配合使用隨機(jī)喚醒線(xiàn)程池中一線(xiàn)程。線(xiàn)程為了檢測(cè)死鎖,它需要遞進(jìn)地檢測(cè)所有被請(qǐng)求的鎖。 線(xiàn)程間通信 其實(shí)就是多個(gè)線(xiàn)程操作同一個(gè)資源,但動(dòng)作不同。示例:在某個(gè)數(shù)據(jù)庫(kù)中,Input輸入人的姓名,性別,Output輸出,兩個(gè)線(xiàn)程同時(shí)作用。思考:1.明確哪些代碼是多線(xiàn)程操作的...

    CocoaChina 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<