2013-05-08 47 views
1

我是新同步主題,在嘗試訪問同步對象時找不到有關使用wait(),notify()notifyAll()方法的任何地方的明確信息。對於〔實施例,如果我們有這樣的代碼:同步多個線程之間的數據

class X extends Thread { 
    int x; 

    public void methodX() 
    { 
     synchronized(this) 
     { 
      //some operations on x 
     } 
    } 
} 

class Y extends Thread { 
    public void methodY(X x) 
    { 
     int z = x.x; 
    } 
} 

我們應該倡導:在methodY()notify()wait()methodX()結束了嗎? 否則,我們不會爲z分配任何值,否則線程將等待,直到X解鎖爲止,而不顯式調用wait()

+0

你想做什麼?包括主要() – 2013-05-08 12:24:20

+2

不,你不應該。由於X.x被多個線程訪問,所以每個訪問都應該簡單地在同一個對象上同步。閱讀Brian Goetz的[Java併發教程](http://docs.oracle.com/javase/tutorial/essential/concurrency/)和Java Concurrency in Practice。還請閱讀wait()和notify()的javadoc以瞭解它們的用途和用途。 – 2013-05-08 12:25:49

+0

請澄清一下......你的要求是'method'的賦值在'methodX'執行之後纔會出現? – 2013-05-08 12:27:15

回答

2

所以給你需要methodY等到methodX已執行,這樣做的一個有效方法是waitnotifynotifyAll。當然還有其他多種方式,但其中一種是有效的。鑑於你甚至可能不需要同步塊。

void methodX(){ 
     // do your work here 
     this.notifyAll(); 
} 

void methodY(X x){ 
    x.wait(); 
    int x = X.x; 
} 

你可能會考慮將阻止代碼的getX方法X但上面會工作,如果(這是個很大的可能),你可以methodX之前保證methodY開始,否則methodY將錯過notify通話。

以上所有說,我同意JB Nizet,你可能會考慮更高層次的機制,如信號量/互斥/等等。這些減輕了複雜性。例如,如果您使用的是CountDownLatch並用1個代碼的計數創建它可能會更強勁...

考慮:

class X{ 
    volatile int x; 
    final CountDownLatch cdl = new CountDownLatch(1); 

    void methodX(){ 
     // do work here 
     cdl.countDown(); 
    } 

    int getX(){ 
     cdl.await(); 
     return x; 
    } 
} 

class Y{ 
    void methodY(X x){ 
     int z = X.getX(); 
    } 
} 

以上將工作每一次,沒有任何排序的風險。