2013-10-22 35 views
0

我對多線程的知識很少。通知給予IllegalMonitorStateException

我期待下面的程序完美運行,但它不工作,併產生以下異常。

Exception in thread "Thread-1" java.lang.IllegalMonitorStateException 
    at java.lang.Object.notify(Native Method) 
    at com.onmobile.client.D.callD(Deadlock.java:76) 
    at com.onmobile.client.B.run(Deadlock.java:50) 
    at java.lang.Thread.run(Unknown Source) 

Java文件

public class Deadlock { 
    C c = new C(); 
    D d = new D(); 

    public static void main(String[] args) {  
     new Deadlock(); 
    } 

    public Deadlock() { 
     A a = new A(d,c); 
     B b = new B(d,c); 

     Thread t1 = new Thread(a); 
     Thread t2 = new Thread(b); 

     t1.start(); 
     t2.start(); 
    } 
} 

class A implements Runnable{ 
    D dObj; 
    C cObj; 

    A(D obj, C obj1){ 
     this.dObj = obj; 
     this.cObj = obj1; 
    } 
    @Override 
    public void run() { 
     cObj.callC(dObj); 
    } 
} 



class B implements Runnable{ 
    D dObj; 
    C cObj; 

    B(D obj, C obj1){ 
     this.dObj = obj; 
     this.cObj = obj1; 
    } 
    @Override 
    public void run() { 
     dObj.callD(cObj); 
    } 
} 


class C{ 
    public synchronized void callC(D dObj){ 
     try { 
      this.wait(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     dObj.callD1(); 
    } 
    public synchronized void callC1(){ 
    } 
} 

class D{ 
    public synchronized void callD(C cObj){ 
     try { 
      Thread.sleep(1000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     }  
     cObj.callC1(); 
     cObj.notify(); 
    } 

    public synchronized void callD1(){ 
    } 
} 

我還以爲裏面CALLC()方法,C類即cObj的對象超出處於等待狀態,同時控制將轉向callD()方法,並有它調用cObj。通知(); 因此,這將喚醒等待對象cObj的等待線程。

但它給我異常。 我想解決我的問題可能是: Java: IllegalMonitorStateException on notify()

,但我沒有正確理解它。

請指導我在哪裏出錯。

回答

0

如果你想通知或等待一個對象,你的線程必須擁有moni你採取行動的對象。

public synchronized void callD(C cObj){ 
    try { 
     Thread.sleep(1000); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    }  
    cObj.callC1(); 
    cObj.notify(); 
} 

在你D類的實例進行同步,如同步的方法總是獲得對象的監視器上,他們「活」這個代碼段。但爲了能夠使用cObj.notify(),您必須獲得cObj實例的監視器,例如,通過在Object

synchronized(cObj) { 
    cObj.notify(); 
} 
4

調用object.notify時,你必須持有的鎖,準確的目標,即:

synchronized(cObj) { 
    cObj.notify(); 
} 

你也應該換用類似的synchronized塊你等待召喚:

synchronized(cObj) { 
    cObj.wait() 
} 

我建議你在Java教程中詳細瞭解它: http://docs.oracle.com/javase/tutorial/essential/concurrency/

+0

感謝Omry。我現在明白了。 – Jayesh

0

notify應該只採取鎖或synchronizing該對象後調用。所以你的情況,你需要的是:

class D{ 
    public void callD(C cObj){ //synchronized not required here 
     try { 
      Thread.sleep(1000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     synchronize(cObj) { //synchornize here on cObj 
      cObj.callC1(); 
      cObj.notify(); 
     } 
    } 
} 

注意:如果你改變你的代碼synchornize callDsynchroniz(cObj)確保您在deadlock場景。恕我直言,只有synchroniz(cObj)應該就足夠了。

0

要在對象上調用notify(),您需要擁有該對象的鎖。在這種情況下調用

cObj.notify(); 

你需要把它包裝成syncronized塊這樣的:

syncronized (cObj) 
{ 
    cObj.notify(); 
}