Java多線程之死鎖的示例分析

小編給大家分享一下Java多線程之死鎖的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

創(chuàng)新互聯(lián)建站專注于許昌網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠(chéng)為您提供許昌營(yíng)銷型網(wǎng)站建設(shè),許昌網(wǎng)站制作、許昌網(wǎng)頁設(shè)計(jì)、許昌網(wǎng)站官網(wǎng)定制、重慶小程序開發(fā)公司服務(wù),打造許昌網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供許昌網(wǎng)站排名全網(wǎng)營(yíng)銷落地服務(wù)。

什么是死鎖?

死鎖是這樣一種情形:多個(gè)線程同時(shí)被阻塞,它們中的一個(gè)或者全部都在等待某個(gè)資源被釋放.由于線程被無限期地阻塞,因此程序不能正常運(yùn)行.形象的說就是:一個(gè)寶藏需要兩把鑰匙來打開,同時(shí)間正好來了兩個(gè)人,他們一人一把鑰匙,但是雙方都再等著對(duì)方能交出鑰匙來打開寶藏,誰都沒釋放自己的那把鑰匙.就這樣這倆人一直僵持下去,直到開發(fā)人員發(fā)現(xiàn)這個(gè)局面.

導(dǎo)致死鎖的根源在于不適當(dāng)?shù)剡\(yùn)用“synchronized”關(guān)鍵詞來管理線程對(duì)特定對(duì)象的訪問.“synchronized”關(guān)鍵詞的作用是,確保在某個(gè)時(shí)刻只有一個(gè)線程被允許執(zhí)行特定的代碼塊,因此,被允許執(zhí)行的線程首先必須擁有對(duì)變量或?qū)ο蟮呐潘栽L問權(quán).當(dāng)線程訪問對(duì)象時(shí),線程會(huì)給對(duì)象加鎖,而這個(gè)鎖導(dǎo)致其它也想訪問同一對(duì)象的線程被阻塞,直至第一個(gè)線程釋放它加在對(duì)象上的鎖.

對(duì)synchronized不太了解的話請(qǐng)點(diǎn)擊這里

舉個(gè)例子

死鎖的產(chǎn)生大部分都是在你不知情的時(shí)候.我們通過一個(gè)例子來看下什么是死鎖.

1.synchronized嵌套.

synchronized關(guān)鍵字可以保證多線程再訪問到synchronized修飾的方法的時(shí)候保證了同步性.就是線程A訪問到這個(gè)方法的時(shí)候線程B同時(shí)也來訪問這個(gè)方法,這時(shí)線程B將進(jìn)行阻塞,等待線程A執(zhí)行完才可以去訪問.這里就要用到synchronized所持有的同步鎖.具體來看代碼:

//首先我們先定義兩個(gè)final的對(duì)象鎖.可以看做是共有的資源.
 final Object lockA = new Object();
 final Object lockB = new Object();
//生產(chǎn)者A
 class ProductThreadA implements Runnable{
   @Override
   public void run() {
//這里一定要讓線程睡一會(huì)兒來模擬處理數(shù)據(jù) ,要不然的話死鎖的現(xiàn)象不會(huì)那么的明顯.這里就是同步語句塊里面,首先獲得對(duì)象鎖lockA,然后執(zhí)行一些代碼,隨后我們需要對(duì)象鎖lockB去執(zhí)行另外一些代碼.
     synchronized (lockA){
     //這里一個(gè)log日志
       Log.e("CHAO","ThreadA lock lockA");
       try {
         Thread.sleep(2000);
       } catch (InterruptedException e) {
         e.printStackTrace();
       }
       synchronized (lockB){
        //這里一個(gè)log日志
         Log.e("CHAO","ThreadA lock lockB");
         try {
           Thread.sleep(2000);
         } catch (InterruptedException e) {
           e.printStackTrace();
         }

       }
     }
   }
 }
 //生產(chǎn)者B
 class ProductThreadB implements Runnable{
 //我們生產(chǎn)的順序真好好生產(chǎn)者A相反,我們首先需要對(duì)象鎖lockB,然后需要對(duì)象鎖lockA.
   @Override
   public void run() {
     synchronized (lockB){
      //這里一個(gè)log日志
       Log.e("CHAO","ThreadB lock lockB");
       try {
         Thread.sleep(2000);
       } catch (InterruptedException e) {
         e.printStackTrace();
       }
       synchronized (lockA){
        //這里一個(gè)log日志
         Log.e("CHAO","ThreadB lock lockA");
         try {
           Thread.sleep(2000);
         } catch (InterruptedException e) {
           e.printStackTrace();
         }

       }
     }
   }
 }
 //這里運(yùn)行線程
ProductThreadA productThreadA = new ProductThreadA();
ProductThreadB productThreadB = new ProductThreadB();

   Thread threadA = new Thread(productThreadA);
   Thread threadB = new Thread(productThreadB);
   threadA.start();
   threadB.start();

分析一下,當(dāng)threadA開始執(zhí)行run方法的時(shí)候,它會(huì)先持有對(duì)象鎖localA,然后睡眠2秒,這時(shí)候threadB也開始執(zhí)行run方法,它持有的是localB對(duì)象鎖.當(dāng)threadA運(yùn)行到第二個(gè)同步方法的時(shí)候,發(fā)現(xiàn)localB的對(duì)象鎖不能使用(threadB未釋放localB鎖),threadA就停在這里等待localB鎖.隨后threadB也執(zhí)行到第二個(gè)同步方法,去訪問localA對(duì)象鎖的時(shí)候發(fā)現(xiàn)localA還沒有被釋放(threadA未釋放localA鎖),threadB也停在這里等待localA鎖釋放.就這樣兩個(gè)線程都沒辦法繼續(xù)執(zhí)行下去,進(jìn)入死鎖的狀態(tài). 看下運(yùn)行結(jié)果:

10-20 14:54:39.940 18162-18178/? E/CHAO: ThreadA lock lockA
10-20 14:54:39.940 18162-18179/? E/CHAO: ThreadB lock lockB

當(dāng)不會(huì)死鎖的時(shí)候應(yīng)該是打印四條log的,這里明顯的出現(xiàn)了死鎖的現(xiàn)象.

死鎖出現(xiàn)的原因

當(dāng)我們了解在什么情況下會(huì)產(chǎn)生死鎖,以及什么是死鎖的時(shí)候,我們?cè)趯懘a的時(shí)候應(yīng)該盡量的去避免這個(gè)誤區(qū).產(chǎn)生死鎖必須同時(shí)滿足以下四個(gè)條件,只要其中任一條件不成立,死鎖就不會(huì)發(fā)生.

  • 互斥條件:線程要求對(duì)所分配的資源進(jìn)行排他性控制,即在一段時(shí)間內(nèi)某 資源僅為一個(gè)進(jìn)程所占有.此時(shí)若有其他進(jìn)程請(qǐng)求該資源.則請(qǐng)求進(jìn)程只能等待.

  • 不剝奪條件:進(jìn)程所獲得的資源在未使用完畢之前,不能被其他進(jìn)程強(qiáng)行奪走,即只能由獲得該資源的線程自己來釋放(只能是主動(dòng)釋放).

  • 請(qǐng)求和保持條件:線程已經(jīng)保持了至少一個(gè)資源,但又提出了新的資源請(qǐng)求,而該資源已被其他線程占有,此時(shí)請(qǐng)求線程被阻塞,但對(duì)自己已獲得的資源保持不放.

  • 循環(huán)等待條件:存在一種線程資源的循環(huán)等待鏈,鏈中每一個(gè)線程已獲得的資源同時(shí)被鏈中下一個(gè)線程所請(qǐng)求。

死鎖的解決方法

說實(shí)話避免死鎖還得再自己寫代碼的時(shí)候注意一下.這里引用別人的解決方法,不過我對(duì)于這些解決方法不是太懂,講的太含糊沒有具體的實(shí)例.

以上是“Java多線程之死鎖的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

網(wǎng)頁題目:Java多線程之死鎖的示例分析
文章鏈接:http://bm7419.com/article26/psdpcg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供自適應(yīng)網(wǎng)站、域名注冊(cè)、建站公司、網(wǎng)站維護(hù)微信小程序企業(yè)建站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

小程序開發(fā)