2013-04-20 84 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

相关问题