Java BigInteger线程安全吗?

Java BigInteger线程安全吗?,java,biginteger,Java,Biginteger,我需要通过多个线程更新全局biginger值--biginger线程安全吗?是不可变的,因此多个线程可以安全访问 旁注:是一个处理多线程访问一段代码(不仅仅是一个变量)的术语。您不能更新BigInteger,读取javadoc,它是不可变的任意精度整数。。要更新BigInteger字段,需要将其替换为新的BigInteger,如下所示 ... bigInteger = bigInteger.add(value); ... 这需要同步,否则会发生两件事: 一个线程更改了该值,但其他线程看不到该更

我需要通过多个线程更新全局
biginger
值--
biginger
线程安全吗?

是不可变的,因此多个线程可以安全访问


旁注:是一个处理多线程访问一段代码(不仅仅是一个变量)的术语。

您不能更新BigInteger,读取javadoc,它是不可变的任意精度整数。。要更新BigInteger字段,需要将其替换为新的BigInteger,如下所示

...
bigInteger = bigInteger.add(value);
...
这需要同步,否则会发生两件事:

  • 一个线程更改了该值,但其他线程看不到该更改

  • 两个或多个线程同时添加,但某些添加丢失


  • BigInteger是线程安全的。 但如果要更新它,应使用如下代码:

    private BigInteger bigInteger = BigInteger.ONE;
    
    public void add(BigInteger plus) {
        bigInteger = bigInteger.add(plus);
    }
    
    所以同步是必要的。

    对象就是一个典型的例子。
    简言之:

    每个不可变的对象都是线程安全的,但是对它的引用

    对于不可变对象而言,状态在整个生命周期内都是固定的。因为没有更改它的选项,所以每个“更改”操作都相当于被一个新对象替换。因此,在特定引用上由N个线程并行执行一系列修改后,结果值很难预测(一些更新可能会丢失-未被注意)。
    课堂上也是如此。为了克服这个限制,我们引入了类。
    不幸的是,JDK中没有“AtomicBigInteger”类。另一种解决方案是用包装对象实例,该实例充当代理,使所有操作同步且原子化

    我提出了以下需要JDK 8的紧凑解决方案:

    final AtomicReference<BigInteger> valueHolder = new AtomicReference(BigInteger.ZERO);
    
    要检查解决方案是否正确,可以使用此代码段,使用并行流将所有小于100的整数相加(这是多线程操作):

    不可变的任意精度整数

    :如果对象的状态在构造后无法更改,则认为该对象是不可变的。最大限度地依赖不可变对象被广泛认为是创建简单、可靠代码的一种合理策略


    这意味着BigInteger是线程安全的。

    请看一看,BigInteger是否线程安全与您无关,因为它是不可变的。因此,您必须用另一个来替换对BigInteger的引用以更新它。您需要确保以线程安全的方式执行此操作。显示BigInteger是线程安全的源文档(或证明它的代码示例)将大大增强此答案。欢迎来到Stack Overflow!这本身并不能保证线程安全,因为AtomicReference上没有原子算术运算。您可以使用compareAndSet来实现旋转方法,但您需要为此扩展您的答案。或者,如果您想建议使用jdk1.8功能,您也应该将其添加到您的答案中。@ErwinBolwidt谢谢您的建议。我刚刚改进了代码示例。效果很好。我试图对列表中的每个数字求和,可能的和超过int/long限制,因此我调整了代码并使用:
    final AtomicReference bsum=new AtomicReference(biginger.ZERO);Arrays.asList(numbers).forEach(number->{bsum.set(bsum.get().add(new-biginger(number));})与noobs交谈时,请注意将“线程安全”与“代码”连接起来。当我们谈论某些代码体(例如Java类)的“线程安全”时,我们谈论的是在多线程环境中代码操作的数据会发生什么情况。许多noobs谈论“同步方法”和“同步块”,却不知道需要保护的是数据。@jameslarge代码本身显然是无状态的,除非它不是不可变的。我很久没有遇到“自我修改代码”了…:)
    
    valueHolder.updateAndGet(x -> x.add(BigInteger.valueOf(10)));
    
    IntStream.range(0, 100).parallel()
            .forEach(i -> valueHolder.updateAndGet(x -> x.add(BigInteger.valueOf(i))));