2017-05-13 88 views
0

爲什麼在開始時立即陷入死鎖 - 它打印出一行然後凍結(建議編輯之後)?
這可能是因爲第一個線程在開始等待之前未命中通知觸發器。
分辨率是多少?初始化時出現死鎖

public class threadTwo{ 
    AtomicInteger i=new AtomicInteger(0); 
    Boolean b=new Boolean(false); 

    class firstThread implements Runnable{ 
     AtomicInteger i; 
     Boolean b; 
     firstThread(AtomicInteger i,Boolean b){ 
      this.i=i; 
      this.b=b; 
     } 
     public void run(){ 
      while(true){ 
       synchronized(i){ 
        try{ 
         while(b==false) 
          i.wait(); 

         if(i.intValue()<30){ 
          i.incrementAndGet(); 
          System.out.println(Thread.currentThread().getId() + " - " + i.intValue()); 
         } 
         b=false; 
         i.notify(); 

        }catch(InterruptedException x){} 
       } 
      } 
     }  
    } 

    class secondThread implements Runnable{ 
     AtomicInteger i; 
     Boolean b; 
     secondThread(AtomicInteger i,Boolean b){ 
      this.i=i; 
      this.b=b; 
     } 
     public void run(){ 
      while(true){ 
       synchronized(i){ 
        try{ 
         while(b==true) 
           i.wait(); 

         if(i.intValue()<40){ 
          i.getAndAdd(2); 
          System.out.println(Thread.currentThread().getId() + " - " + i.intValue()); 
         } 
         b=true; 
         i.notify(); 

        }catch(InterruptedException x){} 
       } 
      } 
     }  
    } 

    void runThread(){ 
     Thread t1 = new Thread(new firstThread(i,b)); 
     Thread t2 = new Thread(new secondThread(i,b)); 
     t1.start(); 
     t2.start(); 
     try{ 
      t1.join(); 
      t2.join(); 
     }catch(Exception e){} 
     System.out.println("Result : " + i.intValue()); 
    } 

    public static void main(String[] args){ 
     new threadTwo().runThread(); 

    } 

} 
+0

布爾值不是引用,它們是值。你在內部類中本地設置b,但不通過threadTwo類,所以b在其他類中永遠不會改變,看起來像?另外,你不需要同步布爾值,它們已經是原子的了(你的兩個線程之間的通信不存在) –

+0

請尊重Java命名約定,類應該以大寫字母開頭。你能解釋代碼實際上做了什麼嗎?此外,你應該嘗試縮小你的代碼庫到必要的部分。請不要這麼做'布爾b =新布爾(假);'除非你有一個真正的好理由。一個「正常的」布爾值就足夠了,你可以用'synchronized(this)'或'synchronized(i)'代替。 – Turing85

+1

@BiepbotVonStirling a)OP使用'布爾'而不是'布爾',這是一個區別,b)'synchronized(...)'有一些其他的效果。它實際上同步整個塊,不僅訪問同步變量,而且也不可能在Java中的基本變量上「同步(...)」。由於Java中的所有變量都是原語或引用,因此除了'double'和'long'之外,對所有變量的訪問都是原子的。 – Turing85

回答

2

問題是b.wait()firstThread。 這個變量b決不會從secondThread得到通知,因爲secondThread在檢查if(b==true)時失敗並立即返回。

但也知道這樣一個事實,即通過變量b同步是非常糟糕的,因爲報表 b=false;b=true;被分配新的實例變量,因此firstThreadsecondThread失去了聯繫。

+0

此外,請注意[Java中的布爾對象是不可變的](http://stackoverflow.com/questions/15194226/why-wrapper-class-like-boolean-in-java-is-immutable)。 –

0

如果我正確地猜測了代碼的意圖,那麼就有不必要的同步和等待通知。試試這個:

public class MyThread 
{ 
    AtomicInteger i = new AtomicInteger(0); 
    Boolean b = new Boolean(false); 

    class FirstThread implements Runnable 
    { 
     AtomicInteger i; 
     Boolean b; 

     FirstThread(AtomicInteger i, Boolean b) 
     { 
      this.i = i; 
      this.b = b; 
     } 

     public void run() 
     { 
      while (i.intValue() < 30) 
      { 
       i.incrementAndGet(); 
       System.out.println(Thread.currentThread().getId() + " - " + i.intValue()); 
      } 
     } 
    } 

    class SecondThread implements Runnable 
    { 
     AtomicInteger i; 
     Boolean b; 

     SecondThread(AtomicInteger i, Boolean b) 
     { 
      this.i = i; 
      this.b = b; 
     } 

     public void run() 
     { 
      while (i.intValue() < 40) 
      { 
       i.getAndAdd(2); 
       System.out.println(Thread.currentThread().getId() + " - " + i.intValue()); 
      } 
     } 
    } 

    void runThread() 
    { 
     Thread t1 = new Thread(new FirstThread(i, b)); 
     Thread t2 = new Thread(new SecondThread(i, b)); 
     t1.start(); 
     try 
     { 
      t1.join(); 
     } 
     catch (InterruptedException exc) 
     { 
      exc.printStackTrace(); 
     } 
     t2.start(); 
     try 
     { 
      t2.join(); 
     } 
     catch (InterruptedException exc) 
     { 
      exc.printStackTrace(); 
     } 
     System.out.println("Result : " + i.intValue()); 
    } 

    public static void main(String[] args) 
    { 
     new MyThread().runThread(); 

    } 
}