2014-03-30 56 views
0

注意:如果此wait和notify使用不正確的語法,請隨意編輯/註釋。Java子類使用wait-notify進行更新

您必須有一個僅由不同的線程進行計算類:

class Foo{ 
    public Foo() { 
     //so thread 2 can know about us. So much for design patterns. 
     synchronized(GlobalStuff) {GlobalStuff.threadpool.add(this);} 
    } 

    Bar b; 
    public Bar emptyBar() { //called by thread #1 ("your" thread). 
    synchronized(this) { 
     b = new Bar(); 
     return b; 
    } 
    } 
    public void makeTest() { //Thread #2 periodically runs this block of code. 
     synchronized(this) { 
     if (b==null) {return;} //do nothing if it is still null. 
     if (b.hasBeenMadeIntoExam();) {return;} //do nothing if it is done already. 

     b.makeMeAnAnnoyingExam(); 
     .... 
     this.notifyAll(); //do we even need the "this"? 
     } 
    } 
} 

這裏是你如何等待它:

//thread 1 runs this block of code. 
Foo fooey = new Foo(); 
Bar b = fooey.emptyBar(); 
while(b.equals(fooey.emptyBar())) { //some statement to check whether it is done or not 
    try { //mandatory try catch statements to keep Java verbose. 
     fooey.makeTest(); 
     fooey.wait(); //wait, and fooey will free us when it calls notifyAll() 
    } catch (InterruptedException ex) {} 
} 
.... //more code that depends on the exam being made. 

我擔心的是B的字段不易變(即使我們將b更改爲易失性),所以當線程2更新它們時,它們不會立即在線程1中出現。請記住,同步和通知不是「深層」的,因此它們不會「精細地更新」狀態的所有子類。我需要擔心嗎?有沒有辦法解決這個問題,而不是手動將「volatile」粘到任何地方?

+2

很難推斷甚至沒有編譯的多線程代碼。在提問之前請注意代碼。 –

回答

0

而不是同步整個實例。您只能同步方法。

Bar b; public synchronized bar emptyBar(){//被線程#1調用(「你的」線程)。 b = new Bar(); return b; }

而不是在Foo中添加​​塊。改變對象的狀態的Bar中的方法synchronize

+0

是的,這種方式阻塞較少,因此性能更高(雖然這對我的真實版本沒有多大幫助)。我的方式會按原樣工作嗎? –

+0

您不會使用此鎖定對象來同步「整個類」。那時它只是另一個鎖。同步一小段代碼總是更好。 – tgkprog

1

我通常避免使用'this'進行同步。而不是使用synchronized(this),定義一個顯式鎖定並與之同步。如果子類需要它,那麼也讓它們可用。例如。

class Foo { 

    protected final Object lock = new Object(); 

    public Bar emptyBar() { 
    synchronized (lock) { 
     ... 
    } 
    } 

    ... 

} 

而不是this.notifyAll(),使用lock.notifyAll();.

只要您希望讀取/寫入的所有字段都在同步(鎖定)塊中被訪問/更新,您可以放心,這些值是最新的。

+0

爲什麼不用這個?子類不能得到它? – tgkprog

+1

@tgkprog'this'可以允許意外的同步範圍蔓延,因爲外部代碼可以同步(fooInstance),這增加了處理多個監視器同步時引入死鎖的可能性。而且,它可以更容易地從後來改變鎖定impl。同步到諸如ReadWriteLock之類的其他東西,而不用擔心可能無法識別的外部代碼(尤其是庫)。 – Mike