BigInteger 线程安全吗?
Is BigInteger Thread safe?
我需要通过多线程更新全局 BigInteger
值 -- BigInteger
线程安全吗?
java.math.BigInteger
是不可变的,因此对于多线程访问是安全的。
旁注:Thread-safety 是一个术语,用于处理多个线程访问 一段代码 (不仅仅是一个变量)。
您无法更新 BigInteger,请阅读 javadoc,它是不可变的任意精度整数。。要更新 BigInteger 字段,您需要将其替换为新的 BigInteger,如下所示
...
bigInteger = bigInteger.add(value);
...
这将需要同步,否则可能会发生两种情况:
一个线程更改了值但其他线程看不到更改
两个或多个线程正在同时添加,但一些添加丢失了。
BigInteger 是线程安全的。
但是你想更新它,你应该使用这样的代码:
private BigInteger bigInteger = BigInteger.ONE;
public void add(BigInteger plus) {
bigInteger = bigInteger.add(plus);
}
所以同步是必要的。
BigInteger objects are an representative example of immutable objects.
简单地说:
Each immutable object is thread-safe, but the reference to it
is not.
对于不可变对象,状态在整个生命周期内都是固定的。因为没有更改它的选项,所以每个 "change" 操作等同于用新对象替换。因此,在 N 个线程对特定引用并行执行一系列修改后,结果值很难预测(一些更新可能会丢失 - 未被注意到)。
同样的故事发生在 Integer class. To overcome that limitation AtomicInteger class was introduced to JDK5.
不幸的是,JDK 中没有“AtomicBigInteger”class。替代解决方案是使用 AtomicReference 包装一个对象实例 - 它作为代理使所有操作同步和原子化。
我提出以下紧凑的解决方案,需要 JDK 8:
final AtomicReference<BigInteger> valueHolder = new AtomicReference(BigInteger.ZERO);
使用这种方法,BigInteger 提供的任何方法都可以重述为 lambda 表达式,例如:
valueHolder.updateAndGet(x -> x.add(BigInteger.valueOf(10)));
要检查解决方案是否正确,您可以使用以下代码片段,它使用并行流(它是多线程操作)对所有小于 100 的整数求和:
IntStream.range(0, 100).parallel()
.forEach(i -> valueHolder.updateAndGet(x -> x.add(BigInteger.valueOf(i))));
BigInteger : Immutable arbitrary-precision integers.
Immutable Objects : An object is considered immutable if its state cannot change after it is constructed. Maximum reliance on immutable objects is widely accepted as a sound strategy for creating simple, reliable code.
这意味着 BigInteger 是线程安全的。
我需要通过多线程更新全局 BigInteger
值 -- BigInteger
线程安全吗?
java.math.BigInteger
是不可变的,因此对于多线程访问是安全的。
旁注:Thread-safety 是一个术语,用于处理多个线程访问 一段代码 (不仅仅是一个变量)。
您无法更新 BigInteger,请阅读 javadoc,它是不可变的任意精度整数。。要更新 BigInteger 字段,您需要将其替换为新的 BigInteger,如下所示
...
bigInteger = bigInteger.add(value);
...
这将需要同步,否则可能会发生两种情况:
一个线程更改了值但其他线程看不到更改
两个或多个线程正在同时添加,但一些添加丢失了。
BigInteger 是线程安全的。 但是你想更新它,你应该使用这样的代码:
private BigInteger bigInteger = BigInteger.ONE;
public void add(BigInteger plus) {
bigInteger = bigInteger.add(plus);
}
所以同步是必要的。
BigInteger objects are an representative example of immutable objects.
简单地说:
Each immutable object is thread-safe, but the reference to it is not.
对于不可变对象,状态在整个生命周期内都是固定的。因为没有更改它的选项,所以每个 "change" 操作等同于用新对象替换。因此,在 N 个线程对特定引用并行执行一系列修改后,结果值很难预测(一些更新可能会丢失 - 未被注意到)。
同样的故事发生在 Integer class. To overcome that limitation AtomicInteger class was introduced to JDK5.
不幸的是,JDK 中没有“AtomicBigInteger”class。替代解决方案是使用 AtomicReference 包装一个对象实例 - 它作为代理使所有操作同步和原子化。
我提出以下紧凑的解决方案,需要 JDK 8:
final AtomicReference<BigInteger> valueHolder = new AtomicReference(BigInteger.ZERO);
使用这种方法,BigInteger 提供的任何方法都可以重述为 lambda 表达式,例如:
valueHolder.updateAndGet(x -> x.add(BigInteger.valueOf(10)));
要检查解决方案是否正确,您可以使用以下代码片段,它使用并行流(它是多线程操作)对所有小于 100 的整数求和:
IntStream.range(0, 100).parallel()
.forEach(i -> valueHolder.updateAndGet(x -> x.add(BigInteger.valueOf(i))));
BigInteger : Immutable arbitrary-precision integers.
Immutable Objects : An object is considered immutable if its state cannot change after it is constructed. Maximum reliance on immutable objects is widely accepted as a sound strategy for creating simple, reliable code.
这意味着 BigInteger 是线程安全的。