<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    和風細雨

    世上本無難事,心以為難,斯乃真難。茍不存一難之見于心,則運用之術自出。

    線程的死鎖

    本文內容

    同步不是改善程序安全性的靈丹妙藥。
    發生死鎖的兩種情況和解決方法。

    同步不是改善程序安全性的靈丹妙藥

    從《線程的同步》一節中我們可以知道,synchronized能保證只有一個線程進入同步方法或同步塊,但為了安全性盲目給多線程程序加上synchronized關鍵字并不是問題解決之道,這不但會降低程序的效率;還有可能帶來嚴重的問題-死鎖。
    死鎖發生在兩個或以上的線程在等待對象鎖被釋放,但程序的環境卻讓lock無法釋放時。下面我們將看到兩種類型的死鎖例子。

    某線程不退出同步函數造成的死鎖

    public class PaintBoard  extends Thread{
      private boolean flag=true;
     
      public void paint(){   
        System.out.println("模擬繪畫");
      }
     
      public synchronized void run(){
        while(flag){
          try{
            paint();
            Thread.sleep(1000);
          }
          catch(InterruptedException ex){
            ex.printStackTrace();
          }
        }
      }
     
      public synchronized void stopDraw(){
        flag=false;
        System.out.println("禁止繪畫");
      }
     
      public static void main(String[] args){
        PaintBoard paintBoard=new PaintBoard();
        paintBoard.start();
        new StopThread(paintBoard);
      }
    }

    public class StopThread implements Runnable{
      private PaintBoard paintBoard;
     
      public StopThread(PaintBoard paintBoard){
        this.paintBoard=paintBoard;
       
        Thread th=new Thread(this);
        th.start();
      }
     
      public void run(){
        while(true){
          System.out.println("試圖停止繪畫過程");
          paintBoard.stopDraw();
          System.out.println("停止繪畫過程完成");
        }
      }
    }

    問題的發生和解決

    剛才的死鎖原因是run()函數中有一個無限循環,一個線程進入后會在其中往復操作,這使它永遠不會放棄對this的鎖定,結果導致其它線程無法獲得this的鎖定而進入stopDraw函數。
    我們把修飾run函數的synchronized取消就能解決問題。 run函數中不會改變任何量,這種函數是不該加上synchronized的。

    兩個線程爭搶資源造成的死鎖.

    public class Desk{
      private Object fork=new Object();
      private Object knife=new Object();
     
      public void eatForLeft(){
        synchronized(fork){
          System.out.println("左撇子拿起叉");
          sleep(1);
          synchronized(knife){
            System.out.println("左撇子拿起刀");
            System.out.println("左撇子開始吃飯");
          }
        }
      }
     
      public void eatForRight(){
        synchronized(knife){
          System.out.println("右撇子拿起刀");
          sleep(1);
          synchronized(fork){
            System.out.println("右撇子拿起叉");
            System.out.println("右撇子開始吃飯");
          }
        }
      }
     
      private void sleep(int second){
        try{
          Thread.sleep(second*1000);
        }
        catch(InterruptedException ex){
          ex.printStackTrace();
        }
      }
     
      public static void main(String[] args){
        Desk desk=new Desk();
        new LeftHand(desk);
        new RightHand(desk);
      }
    }

    public class LeftHand implements Runnable{
      private Desk desk;
     
      public LeftHand(Desk desk){
        this.desk=desk;
       
        Thread th=new Thread(this);
        th.start();
      }
     
      public void run(){
        while(true){
          desk.eatForLeft();
        }
      }
    }

    public class RightHand implements Runnable{
      private Desk desk;
     
      public RightHand(Desk desk){
        this.desk=desk;
       
        Thread th=new Thread(this);
        th.start();
      }
     
      public void run(){
        while(true){
          desk.eatForRight();
        }
      }
    }

    問題的發生和解決

    這部分程序中于兩個線程都要獲得兩個對象的鎖定才能執行實質性操作,但運行起來卻發現其它線程持有了自己需要的另一個鎖定,于是停在Wait Set中等待對方釋放這個鎖定,結果造成了死鎖。
    解決這個問題的方法是保證鎖對象的持有順序,如果兩個加上了同步的函數都是先刀后叉的形式則不會發生問題。

    小結

    同步不是改善程序安全性的靈丹妙藥,盲目同步也會導致嚴重的問題-死鎖.
    某線程持續不退出同步函數會造成死鎖.解決方法是去掉或更換不正確的同步。
    兩個線程都等待對方釋放自己需要的資源也會造成死鎖.這種情況的解決方法是確保同步鎖對象的持有順序。

    posted on 2008-02-22 14:11 和風細雨 閱讀(786) 評論(0)  編輯  收藏 所屬分類: 線程

    主站蜘蛛池模板: 日韩精品免费一线在线观看| 久久久久久久综合日本亚洲| 日本免费中文字幕在线看| 成人免费视频网站www| 国产亚洲人成无码网在线观看| 免费a级黄色毛片| 国产成人无码区免费A∨视频网站| 国产精品成人免费观看| 国产亚洲人成在线影院| 美女视频黄.免费网址| EEUSS影院WWW在线观看免费| www成人免费视频| 97久久国产亚洲精品超碰热| 亚洲永久在线观看| 亚洲色www永久网站| 蜜芽亚洲av无码一区二区三区| 久久久久久亚洲精品成人| 亚洲视频在线观看地址| 亚洲一级毛片免费在线观看| 国产日本亚洲一区二区三区| 亚洲爆乳无码精品AAA片蜜桃| 亚洲黄色免费在线观看| 亚洲一线产区二线产区精华| 亚洲人成色4444在线观看| 免费福利在线观看| 99久久国产精品免费一区二区| 57pao国产成视频免费播放| 国语成本人片免费av无码| 免费无码又爽又刺激网站| 99热这里只有精品免费播放| 国产一卡2卡3卡4卡无卡免费视频 国产一卡二卡3卡四卡免费 | 国产卡一卡二卡三免费入口| 免费看大黄高清网站视频在线| 亚洲精品在线视频| 免费中文字幕在线观看| 337p日本欧洲亚洲大胆裸体艺术 | 免费在线观看的网站| 国产又大又长又粗又硬的免费视频| 亚洲免费日韩无码系列 | 免费萌白酱国产一区二区| 337p日本欧洲亚洲大胆裸体艺术 |