2013-04-20 90 views
1

最近我讀了「實踐中的Java併發」 Section - >「3.4.2示例:使用volatile來發布不可變對象」。使用volatile來發布不可變對象是否安全?

但是;我無法安靜地理解它。 這是情況!

不可變對象是:

@Immutable 
class OneValueCache { 
    private final BigInteger lastNumber; 
    private final BigInteger[] lastFactors; 
    public OneValueCache(BigInteger i, BigInteger[] factors) { 
     lastNumber = i; 
     lastFactors = Arrays.copyOf(factors, factors.length); 
    } 
    public BigInteger[] getFactors(BigInteger i) { 
     if (lastNumber == null || !lastNumber.equals(i)) 
      return null; 
     else 
      return Arrays.copyOf(lastFactors, lastFactors.length); 
    } 
} 

假設我們有這樣

public class MyServlet { 
private volatile OneValueCache immutableValue; 
. 
. 

public void service(){ 
      . 
      // what this function do : gets value from immutable object increments its 
      // value and creates new Immutable object and put it back. 
      // 
      . 
    immutableValue = new OneValueCache(lastNumber, lastFactor[]); 
    . 
    . 
    . 
} 
. 
. 
. 
} 

一個servlet據該書MyServlet是線程安全的,因爲它發佈不可變對象與volatile關鍵字!

但我認爲這裏有一個問題!

假設:

線程1在時間0讀取immutableValue的值,以它的堆棧變種;

線程2在時間0讀取從immutableValue值到它的堆棧var;

線程1在時間1遞增堆棧變量中的值並創建新的OneValueCache 對象 - 它是不可變的 - 並將其放入immutableValue字段變量中;

線程2在時間2遞增堆棧變量的值並創建新的OneValueCache 對象 - 它是不可變的 - 並將其放入immutableValue字段變量中;

這樣我們就失去了Thread1更新,所以這裏沒有ThreadSafty!

相反的書上說:

「 供不變的相關 多個狀態變量,並用來 確保及時知名度揮發性引用一個不變的持有者對象的組合,使得VolatileCachedFactorizer到是線程安全的 即使它沒有明確的鎖定 「

任何人都可以幫助我什麼我在這裏失蹤?

p.s:爲了更清楚,我知道數據一致性在這裏。我們不能有無效的OneValueCache狀態。但是當我的線程序列顯示時,這裏有丟失更新的機會。所以班級不是線程安全的!

回答

3

不可變性意味着線程的安全性,因爲一旦創建線程就不能修改它,所以線程中的值將保持一致。

在上面的例子中,「private volatile OneValueCache immutableValue」一次只能保存一個值,所以如果線程1先更新然後線程2更新了引用值,那麼最後一個值將由「onevaluecache」表示並更新Thread因爲只存儲一個參考值,所以1會丟失。

OneValueCache狀態中提到的步驟中沒有任何一點是不一致的,所以它是線程安全的。

編輯:某些情況下,國家將不會是一致的是:

  1. 如果immutableValue變量是不揮發則每個線程都保存自己的副本,這意味着高速緩存將無法正常工作。

  2. 如果OneValueCache類是可變的,那麼多線程將同時改變它的值,這意味着狀態將不一致,因此不是線程安全的。

+0

我對數據一致性的看法不確定,我們在這裏很安全,但是我們可能在這裏丟失了更新,導致類不是線程安全的! – 2013-04-21 09:00:25

+0

它的singlevaluecache和只有最後更新可以留下來!所有以前的更新將不得不被垃圾收集,不是。我不明白你是什麼意思的丟失更新 – Lokesh 2013-04-21 09:05:40

+0

看到線程1和2執行的問題和順序 – 2013-04-21 09:13:43

相關問題