2015-05-29 72 views
3

下面的代碼將工作,但我微微反感不必編寫,將isRunning()方法:我可以同步讀取控制變量嗎?

class Test { 
    private boolean running; 
    public void startX() { 
     synchronized(this) { 
      running = true 
     } 
     while (isRunning()) { 
      //do something 
     } 
    } 
    public synchronized void stopX() { 
     running = false; 
    } 
    private synchronized boolean isRunning() { 
     return running; 
    } 
} 

我可以同步在一些其他的方式,在while (running){}running變量的讀取,還是我寫的isRunning()方法?同樣的問題也適用於其他控制變量爲好,如

for (;running;) {} 

if (running) {} 

在所有這些情況下,它好像你被迫寫一個毫無意義的方法來獲得同步正確。我錯過了什麼嗎?

+2

只是讓''running' volatile'。 –

回答

2

您可以使運行字段不穩定。讓字段變成易變的,讓JVM注意到它應該改變該字段對其他線程可見。 「錯過更新」警告是針對您希望讀取值並根據該值進行更新的情況,這在此似乎不適用。 多線程可以寫入此字段,如果他們正在做的是設置一個布爾標誌,那麼這不會是一個問題。

或者,如果您試圖取消某個線程,則此線程上已經有一個等效標誌(並且可見性問題已得到解決)。您可以在線程上調用中斷,Runnable中的代碼可以查詢Thread.currentThread().isInterrupted()以判斷它是否被中斷。這比使用自己的標誌更可取,因爲中斷會導致線程在等待或睡眠時喚醒。用自己的國旗,你必須等到控制權到達可以測試國旗的地方。

3

如果您只是將running的值重置一次以指定停止,那麼您可能可以使用volatile關鍵字。

但是,如果您需要多次啓動和停止,這將不起作用。這是因爲揮發性場「可能會錯過更新」

下面就來解釋一個鏈接時volatile作品在類似案例link

這裏是從該鏈接的代碼示例櫃面它會死:

public class StoppableTask extends Thread { 
    private volatile boolean pleaseStop; 

    public void run() { 
    while (!pleaseStop) { 
     // do some stuff... 
    } 
    } 

    public void tellMeToStop() { 
    pleaseStop = true; 
    } 
    } 

如果您需要多次啓動和停止,那麼您需要使用Java 5併發鎖定對象之一或顯式同步

+0

感謝您的回答。不幸的是,我不能保證只有一個線程會寫入這個值,所以它必須同步AFAIK – user1675642

+0

@ user1675642'volatile'保證了不同線程之間的可見性,因此對於這種沒有問題的特殊情況。考慮到在執行過程中寫入'pleaseStop'將始終爲真,因此不會有更新未命中的機會。 –

+0

@ E_net4'pleaseStop'來自我鏈接到的代碼示例博客。如果他們的'startX()'被再次調用,OP可能會將標誌置位。 – dkatzel

0

只需加上其他人的答案即可取笑volatile。 或者,您可以爲檢查創建一個類。 我已經使變量爲static,所以所有的線程都將指向同一個對象。

class Runner{ 

boolean static running=true; 

public static synchronized boolean getRunning(){ 
    return running; 
} 

public static synchronized boolean setRunning(boolean r){ 
    running=r; 
} 
} 

注:

如果您不需要全局變量,然後取出static

+0

我可以永遠不會批准使用波動字段的全局監視器同步。 –

+0

@ E_net4它是一個意見交換的問題。我有一個包含超過1000個線程的程序,運行的行爲相同。迄今沒有發生災難性事件。 – nafas

+0

不改變它不是可擴展解決方案的事實。使它變爲靜態意味着你甚至不能創建它的多個實例。 –

相關問題