Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is BigInteger Thread safe?

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

like image 326
Shiv Avatar asked Sep 15 '15 03:09

Shiv


People also ask

How many bits can BigInteger hold?

The BigInteger class stores a number as an array of unsigned, 32-bit integer "digits" with a radix, or base, of 4294967296.

Is BigInteger slow Java?

The standard library BigInteger class in Java is known to be notoriously slow (at least for Java 7 and earlier, and I doubt Java 8 is any different).

Does BigInteger have a limit?

BigInteger has no cap on its max size (as large as the RAM on the computer can hold).

Is BigInteger bigger than long?

3. BigInteger Larger Than Long. MAX_VALUE. As we already know, the long data type is a 64-bit two's complement integer.


2 Answers

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))));
like image 72
Karol Król Avatar answered Oct 30 '22 17:10

Karol Król


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.

like image 38
Evgeniy Dorofeev Avatar answered Oct 30 '22 18:10

Evgeniy Dorofeev