2017-02-10 85 views
2

我與一些併發的遺留代碼掙扎,不知是否stopLatch和/或mode應該是volatile這是否併發遺留代碼需要揮發性

public class MyClass { 

    private final ExecutorService executor = Executors.newSingleThreadExecutor(); 
    private MyModeEnum mode = MyModeEnum.NONE; 
    private CountDownLatch stopLatch; 

    public synchronized void start(final MyModeEnum mode) { 
     assert mode != null && mode != MyModeEnum.NONE; 
     if (isRunning()) { 
      // Throw an exception. 
     } 
     this.mode = mode; 
     stopLatch = new CountDownLatch(1); 
     executor.execute(() -> { 
      try { 
       // Pre and post operations not under control around stopLatch.await(). 
      } catch (final Exception e) { 
       stop(); 
       // Further exception handling. 
      } finally { 
       MyClass.this.mode = MyModeEnum.NONE; 
      } 
     }); 
    } 

    public synchronized void stop() { 
     if (!isRunning()) { 
      return; 
     } 
     stopLatch.countDown(); 
    } 

    public boolean isRunning() { 
     return mode != MyModeEnum.NONE; 
    } 

    public MyModeEnum getMode() { 
     return mode; 
    } 

} 

精心的解釋非常讚賞。

編輯:我不能歸結爲一般問題/答案,如When exactly do you use the volatile keyword in Java?對這個特定的問題。

+1

同步塊有當他們進入和退出所有線程同步,所以我不認爲'volatile'是必要的。 – khelwood

+1

我會說只有'mode'需要'volatile',因爲任何變化都需要對其他線程可見。注意:'assert'好像和'isRunning()'做的是一樣的工作,我錯了嗎? – sp00m

+4

'isRunning() ''不'同步',所以'mode'應該是'volatile' ' –

回答

0

根據最upvoted評論:

  • Mick Mnemonic

    isRunning()不​​,所以mode應該volatile

  • Brian Goetz

    您對mode數據競爭。它是從同步塊外部訪問的。首選應該是同步isRunninggetMode;製作模式volatile是一個更高級的玩法。 (先走了,再飛。)