我需要通过多个线程更新全局BigInteger
值 - BigInteger
线程安全吗?
答案 0 :(得分:10)
BigInteger 对象是immutable objects的代表性示例 简单地说:
每个不可变的对象都是线程安全的,但引用它 is not 强>
对于不可变对象,状态在整个生命周期内都是固定的。因为没有改变它的选择因此每个"改变"操作相当于用新对象替换。因此,在特定参考上的N个线程并行执行一系列修改之后,结果值很难预测(某些更新可能会丢失 - 未被注意)。
同样的故事是Integer课程。为克服这一限制,{strong> AtomicInteger 课程被引入JDK5
不幸的是,没有" AtomicBigInteger " JDK中的类。替代解决方案是使用 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))));
答案 1 :(得分:2)
您无法更新BigInteger,读取javadoc,它的不可变的任意精度整数。。要更新BigInteger字段,您需要将其替换为新的BigInteger,如此
...
bigInteger = bigInteger.add(value);
...
这将需要同步,否则可能会发生两件事:
一个线程更改了值,但其他线程没有看到更改
两个或多个线程同时添加但有些添加丢失。
答案 2 :(得分:1)
java.math.BigInteger
是不可变的,因此多线程访问是安全的。
旁注:Thread-safety是一个术语,用于处理访问代码的多个线程(不仅仅是变量)。
答案 3 :(得分:0)
BigInteger是线程安全的。 但是你想要更新它,你应该使用这样的代码:
GT
所以同步是必要的。
答案 4 :(得分:0)
BigInteger:不可变任意精度整数。
Immutable Objects:如果一个对象的状态在构造后无法改变,则该对象被认为是不可变的。最大限度地依赖不可变对象被广泛接受为用于创建简单,可靠代码的合理策略。
这意味着BigInteger是线程安全的。