最近我读了“实践中的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