2016-03-07 61 views
1

說我有2個實例變量和以下的方法(簡化了此問題)一個類:使用的AtomicBoolean代替同步塊的

private final Object lock = new Object(); 
private boolean running; 

public MyClass() { 
    synchronized(lock) { 
     running = false; 
    } 
} 
public void methodA() { 
    synchronized(lock) { 
     running = true; 
    } 
} 
public void methodB() { 
    synchronized(lock) { 
     if (!running) { 
      return; 
     } 
    } 
} 

我對着這個代碼,並閱讀有關AtomicBoolean後,我認爲有人可能適合在這裏,尤其是在看MyClass構造函數和methodA後。但我不太確定methodB

假設這些方法可以由多個線程被調用,將下面是線程安全的?:

private AtomicBoolean running; 

public MyClass() { 
    running = new AtomicBoolean(false); 
} 
public void methodA() { 
    running.set(true); 
} 
public void methodB() { 
    if (!running.get()) { 
     return; 
    } 
} 

running.get()保證看到通過從另一個線程running.set(true)running.set(false)更新?

回答

2

在你的例子中,一個簡單的volatile boolean就足夠了,因爲你似乎只是在做原子操作。如果您需要諸如compareAndSet之類的方法,AtomicBoolean很有用。

所以在回答你的問題時,是的,當使用volatile booleanAtomicBoolean時,其他線程將看到變量的更新。

+0

我不太確定。如果有多個閱讀器和_一個作家,那麼_volatile_保證就足夠了。但是,現在有多個作家,我不確定是否保證_volatile_的使用。 –

+2

查看AtomicBoolean的來源 - 如果您不使用compareAndSet方法,則它基本上是一個對象中的易失性布爾值。在任何情況下,多個作家都不是問題。 –

+0

根據[this](http://tutorials.jenkov.com/java-concurrency/volatile.html)(不知道它有多準確),顯然如果有多個編寫者,只要新的寫入值不要依賴於以前的值,但只要你需要檢查前一個值,然後根據前一個值設置一個新值,那麼'volatile'是不夠的。 –

0

是的。來自AtomicBoolean的Javadoc:

可自動更新的{@ code boolean}值。

這意味着,任何更新AtomicBoolean不可分割。所以,我會考慮這樣使用AtomicBoolean線程安全

你仍然應該考慮把AtomicBoolean最後聲明:

private final AtomicBoolean running;

+2

任何'boolean'變量的更新都是不可分割的。 'AtomicXxxxxxx'類爲您提供了兩件事:(a)它們爲您提供對原始值的volatile類似訪問,以及(b)它們爲您提供'getAndSet()','compareAndSet() ,'incrementAndGet()'等等。 –

1

一般來說,這些代碼塊是不相等的methodB,因爲閱讀volatile變量不創建同步順序。

想象一下,你在你的類中的一些其他領域int x = 42,即在的methodB更新:

public void methodB() { 
    if (!running.get()) { 
     return; 
    } 
    if (x < 50) x++; // just example 
} 

那麼你有多個線程調用methodB

  • 在使用synchronized關鍵字,更新對所有線程都安全且可見。
  • 使用的AtomicBoolean /揮發性可見性,則打破

如果沒有與變量更新沒有這樣的情況,任務就是保證了methodA之間的可見性 - 的methodB序列,那麼它的確定 - 的AtomicBoolean就足夠了這一點。

+0

你說如果我「改變一些變量」...你的意思是如果我改變它在情況1的同步塊內,並且緊跟在使用AtomicBoolean/volatile的if塊之後2? –

+0

@JackmeriusTacktheritrix增加了一個例子 – AdamSkywalker

+0

對,'x'的增量不是線程安全的。在實際的代碼中,在if塊之後沒有不安全的更新,所以我認爲我應該沒問題。 –