gpt4 book ai didi

java - 使用 volatile 发布不可变对象(immutable对象)是否安全?

转载 作者:行者123 更新时间:2023-11-29 03:34:49 25 4
gpt4 key购买 nike

最近看了《Java并发实战》 第 --> “3.4.2 示例:使用 volatile 发布不可变对象(immutable对象)”。

但是;我无法静静地理解它。情况是这样的!

不可变对象(immutable对象)是:

@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);
}
}

假设我们有这样一个 servlet

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[]);
.
.
.
}
.
.
.
}

根据这本书,MyServlet 是线程安全的,因为它发布了带有 volatile 关键字的不可变对象(immutable对象)!

不过我觉得这里有问题!

假设:

线程 1 在时间 0 中将 immutableValue 中的值读取到其堆栈变量中;

线程 2 在时间 0 中将 immutableValue 中的值读取到它的堆栈变量中;

时间 1 中的线程 1 递增堆栈变量中的值并创建新的 OneValueCache object - 这是不可变的 - 并将其放入 immutableValue 字段变量中;

线程 2 在时间 2 中递增堆栈变量中的值并创建新的 OneValueCache object - 这是不可变的 - 并将其放入 immutableValue 字段变量中;

这样我们就丢失了 Thread1 更新,所以这里没有 ThreadSafty!

相反书上说:

<强>”这种不可变持有人对象的组合由不变量关联的多个状态变量,以及用于确保其及时可见性,允许 VolatileCachedFactorizer 是线程安全的即使它没有显式锁定。"

任何人都可以帮助我我在这里缺少什么吗?

p.s:更清楚地说,我知道这里保持数据一致性。我们不能有无效的 OneValueCache 状态。但正如我的线程序列所示,这里有可能丢失更新。所以这个类不是线程安全的!

最佳答案

不变性意味着线程安全,因为一旦创建就没有线程可以修改它,因此值将在线程之间保持一致。

在上面的例子中,“private volatile OneValueCache immutableValue”一次只能保存一个值,所以如果线程 1 先更新然后线程 2 更新引用值,那么最后一个值将由“onevaluecache”和线程 1 的更新表示将会丢失,因为您只存储了一个引用值。

在您提到的步骤中,OneValueCache 状态的任何一点都不一致,因此它是线程安全的。

编辑:状态不一致的一些情况是:

  1. 如果 immutableValue 变量不是易变的,那么每个线程都会存储自己的副本,这意味着缓存将无法正常工作。

  2. 如果 OneValueCache 类是可变的,那么多个线程将同时更改其值,这意味着状态将不一致,因此不是线程安全的。

关于java - 使用 volatile 发布不可变对象(immutable对象)是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16119871/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com