最近我讀了「實踐中的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狀態。但是當我的線程序列顯示時,這裏有丟失更新的機會。所以班級不是線程安全的!
我對數據一致性的看法不確定,我們在這裏很安全,但是我們可能在這裏丟失了更新,導致類不是線程安全的! – 2013-04-21 09:00:25
它的singlevaluecache和只有最後更新可以留下來!所有以前的更新將不得不被垃圾收集,不是。我不明白你是什麼意思的丟失更新 – Lokesh 2013-04-21 09:05:40
看到線程1和2執行的問題和順序 – 2013-04-21 09:13:43