8

I have a requirement to update a global BigInteger value via multiple threads -- is BigInteger thread safe?

eebbesen
  • 5,070
  • 8
  • 48
  • 70
Shiv
  • 85
  • 1
  • 6
  • 1
    Please have a look on this http://stackoverflow.com/questions/890968/what-is-the-purpose-of-java-math-mutablebiginteger – Subodh Joshi Sep 15 '15 at 04:32
  • 1
    Whether BigInteger is threadsafe is irrelevant to you as it is immutable. So you have to replace the reference to the BigInteger with another one to update it. And you need to make sure that *you* do that in a thread safe manner. – Erwin Bolwidt Sep 15 '15 at 10:11

5 Answers5

13

BigInteger objects are an representative example of immutable objects.
To put it simply:

Each immutable object is thread-safe, but the reference to it is not.

For immutable objects the state is fixed for an entire lifetime. Because there is no option to change it therefore each "change" operation is equivalent to replacement by a new object. So after series of modifications performed parallely by N threads on a specific reference the result value is hard to predict (some updates could be lost - unnoticed).
The same story is with Integer class. To overcome that limitation AtomicInteger class was introduced to JDK5.
Unfortunately there is no "AtomicBigInteger" class in JDK. The alternate solution is to wrap an object instance with AtomicReference - which works as a proxy that makes all operations synchronised and atomic.

I propose a following compact solution that requires JDK 8:

final AtomicReference<BigInteger> valueHolder = new AtomicReference(BigInteger.ZERO);

Using this approach any method provided by BigInteger could be restated as a lambda expression, e.g.:

valueHolder.updateAndGet(x -> x.add(BigInteger.valueOf(10)));

To check if the solution is correct you may use this code snippet that sums up all integers lower than 100 using parallel streams (it is multithread operation):

IntStream.range(0, 100).parallel()
        .forEach(i -> valueHolder.updateAndGet(x -> x.add(BigInteger.valueOf(i))));
Karol Król
  • 3,320
  • 1
  • 34
  • 37
  • 1
    That doesn't make it thread safe by itself as there are no atomic arithmetic operations on AtomicReference. You can use compareAndSet to implement a spinning approach but you would need to expand your answer for that. Or if you want to suggest using jdk1.8 functionality you should also add that to your answer. – Erwin Bolwidt Sep 15 '15 at 10:15
  • @ErwinBolwidt Thanks for an advice. I just improved code sample. – Karol Król Sep 15 '15 at 10:32
  • Worked great. I was trying to sum every number in a list with the possible sum exceeding the int/long restrictions, so I tweaked the code and used: `final AtomicReference bsum = new AtomicReference(BigInteger.ZERO); Arrays.asList(numbers).forEach(number -> {bsum.set(bsum.get().add(new BigInteger(number)));});` – Kartik Chugh Dec 17 '18 at 00:09
2

You cannot update BigInteger, read javadoc, it's Immutable arbitrary-precision integers.. To update a BigInteger field you will need to replace it with a new BigInteger, like this

...
bigInteger = bigInteger.add(value);
...

and this will require synchronization otherwise two things may happen:

  1. one thread changed the value but other threads do not see the change

  2. two or more threads are adding simultaneously but some addings are lost.

Erwin Bolwidt
  • 30,799
  • 15
  • 56
  • 79
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
1

java.math.BigInteger is immutable and as such it is safe for access by multiple threads.

Side-note: Thread-safety is a term that deals with multiple threads accessing a piece of code (not just a variable).

Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129
  • 1
    Be careful about connecting "thread safety" with "code" when you're talking to noobs. When we talk about the "thread safety" of some body of code (e.g., a Java class), we are talking about what can happen to the _data_ that the code operates on in a multi-threaded environment. A lot of noobs talk about "synchronized methods", and "synchronized blocks", without ever understanding that it's the data that need protection. – Solomon Slow Sep 16 '15 at 22:43
  • @jameslarge the code itself is obviously stateless unless it's not immutable. I didn't run into "self modifying code" for a long time now... :) – Nir Alfasi Sep 16 '15 at 23:11
0

The BigInteger is thread safe. But you want update it,you should use code like this:

private BigInteger bigInteger = BigInteger.ONE;

public void add(BigInteger plus) {
    bigInteger = bigInteger.add(plus);
}

so synchronize is necessary.

yc wang
  • 17
  • 2
  • 2
    Source documentation showing that BigInteger is threadsafe (or a code sample that proves it) would greatly enhance this answer. Welcome to Stack Overfllow! – David L Sep 15 '15 at 05:33
0

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.

This mean BigInteger is thread-safe.

Community
  • 1
  • 1
YoungHobbit
  • 13,254
  • 9
  • 50
  • 73