18

As Integer class is also immutable class and we know that immutable class is thread-safe what is the need of Atomic Integer. I am confused . Is it the reason that reads and write of immutable objects need not be atomic whereas read and write of atomic integer is atomic . That means atomic classes are also thread-safe.

user18424
  • 401
  • 1
  • 3
  • 8
  • which class to use when ?? – user18424 Aug 09 '16 at 09:31
  • 5
    Well, one is mutable, the other immutable. So, you *can* use `AtomicInteger` when you need a mutable value (other options exist), you can't use `Integer`. – Andy Turner Aug 09 '16 at 09:31
  • 2
    You can use `AtomicInteger` when you need a **thread-safe** mutable value, not just a mutable value... – eduardogr Aug 09 '16 at 09:38
  • +1 @EduGR to specify thread-safe mutable value. The classes in atomic package like AtomicInteger works on the principle of volatile variables which gets read/written in memory to persist changes in multi-threaded environment. – ankidaemon Aug 09 '16 at 09:49

5 Answers5

11

AtomicInteger is used in multithreaded environments when you need to make sure that only one thread can update an int variable. The advantage is that no external synchronization is requried since the operations which modify it's value are executed in a thread-safe way.

Consider the followind code:

private int count;

public int updateCounter() {
   return ++count;
}

If multiple threads would call the updateCounter method, it's possible that some of them would receive the same value. The reason it that the ++count operation isn't atomical since isn't only one operation, but made from three operations: read count, add 1 to it's value and write it back to it. Multiple calling threads could see the variable as unmodified to it's latest value.

The above code should be replaced with this:

private AtomicInteger count = new AtomicInteger(0);
public int updateCounter() {
    return count.incrementAndGet();
}

The incrementAndGet method is guaranteed to atomically increment the stored value and return it's value without using any external synchonization.

If your value never changes, you don't have to use the AtomicInteger, it's enought to use int.

Slimu
  • 2,301
  • 1
  • 22
  • 28
6

AtomicInteger is thread safe (in fact, all classes from java.util.concurrent.atomic package are thread safe), while normal integers are NOT threadsafe.

You would require 'synchronized' & 'volatile' keywords, when you are using an 'Integer' variable in multi-threaded environment (to make it thread safe) where as with atomic integers you don't need 'synchronized' & 'volatile' keywords as atomic integers take care of thread safety.

Also, I would recommend the below helpful tutorial on the same subject: http://tutorials.jenkov.com/java-concurrency/compare-and-swap.html

Please refer below oracle doc for more information on 'atomic' package: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html

Vasu
  • 21,832
  • 11
  • 51
  • 67
  • 1
    Normal Integer is thread safe only when you use along with 'synchronized' & 'volatile' keywords. – Vasu Aug 09 '16 at 10:10
  • @developer Integer is immutable and therefore is thread-safe by default, no synchronized or volatile needed. However, the downside of immutability is that the value can never change. If you need a changing value use AtomicInteger or some other method or volatile/synchronized keywords. – puhlen Aug 09 '16 at 13:53
3

While immutable objects are thread-safe by definition, mutable objects can be thread safe too.

That is precisely the purpose of the Atomic... classes (AtomicInteger, AtomicBoolean, and so on).

The various ...get... and ...set... methods allow thread-safe access and mutation of the object.

Not surprisingly, the class is declared in the java.util.concurrent package.

You only have to browse the API for the java.util.concurrent.atomic package:

A small toolkit of classes that support lock-free thread-safe programming on single variables.

Mena
  • 47,782
  • 11
  • 87
  • 106
  • Atomic class should have better performance than immutable wrapper classes i think – user18424 Aug 09 '16 at 09:47
  • 3
    @user18424 Since you can't really use them for the same purpose, you think wrong. There's no logical way to compare performance between those 2 classes. – Kayaman Aug 09 '16 at 09:56
  • @user18424 not really. Within a single-threaded context, you want to stick to `Number`s actually. It all depends on the usage. – Mena Aug 09 '16 at 09:56
2

Consider a variable

int myInt = 3;

AtomicInteger relates to myInt.

Integer relates to 3.

in other words, your variable is mutable and can change it's value. While the value 3 is an integer literal, a constant, an immutable expression.

Integers are object representations of literals and are therefore immutable, you can basically only read them.

AtomicIntegers are containers for those values. You can read and set them. Same as asigning a value to variable. But different to changing the value of int variable, operations on an AtomicInteger are atomic.

For example this is not atomic

if(myInt == 3) {
   myInt++; 
}

This is atomic

AtomicInteger myInt = new AtomicInteger(3);

//atomic
myInt.compareAndSet(3, 4);
Gerald Mücke
  • 10,724
  • 2
  • 50
  • 67
  • While this answer does seem to contain the general gist of it, an `AtomicInteger` cannot refer to an `int` variable, so your example on the first 3 lines is just confusing. – Kayaman Aug 09 '16 at 10:05
  • sorry, I'm no native speaker, I dont mean refer as in "java reference" but more in the sense of "milk refers to cow as whool refers to sheep", but maybe "refer" is not the right word in that case, would "relate" be better? – Gerald Mücke Aug 09 '16 at 10:52
-1

I think the main difference between AtomicInteger and normal immutable Integer will come into the picture, once we understand why even immutable Integers are not thread-safe.

Let's see with an example.

Suppose, we have a value of int count = 5, which is being shared by two different threads named T1 and T2 with both reading and writing at the same time.

We know that, if there is any value being reassigned into an immutable object, the old object remains at the pool and the new one takes over.

Now, when T1 and T2 are updating their values into count variable, Java might take this value into some cache and will do the set operations there and we won't know when JVM will write the updated value into main memory, so there might be a possibility that one of the threads may be updating the value into a totally stale value.

This brings us to the volatile keyword.

Volatile - This keyword ensures that all the I/O operations on any variable will take place on the main memory so that all the threads are working with the most updated value.

Consider, if 1 Thread is writing and all other threads are reading then, volatile will solve our problem, but if all the threads are reading and writing on the same variable at the same time, then we need synchronizing to ensure thread-safety.

Volatile keyword does not ensure thread-safety.

Now, coming to why AtomicIntegers. Even if are using syncrhonized keyword to ensure thread-safety, the actual update operation of count variable will be a three step process.

  1. get updated value of count variable
  2. increment the value by 1
  3. set the value to count variable

This is why it takes a slightly longer time to update any value for normal Integers to update values once the thread safety is taken into consideration.

**AtomicIntegers solve this problem furthermore of thread safety and also faster updates by an optimized lock-free algorithm called Compare-And-Swap (CAS method).

They perform all the update operations atomically as a single-step process. **

Debashis
  • 81
  • 1
  • 9
  • Reference here - https://stackoverflow.com/questions/9303532/immutable-objects-are-thread-safe-but-why#:~:text=Actually%20immutable%20objects%20are%20always,its%20references%20may%20not%20be.&text=Going%20back%20to%20basic%3A%20Thread,done%20by%20any%20other%20thread. – Debashis Jun 30 '22 at 11:08
  • AtomicInteger still has to load/increment/store, it just bundles those 3 steps into an atomic RMW transaction. (On some CPUs like x86 or ARMv8.1, using a special instruction that does a full fetch_add operation. Not a CAS retry loop, that would be even slower. But on many other ISAs, it does need an LL/SC retry loop.) It's slower than separate load / increment / store, especially for a value that was already hot in L1d cache, because the CPU has to do extra work to make sure it hangs on to that cache line for the duration of the internal load/add/store operations. – Peter Cordes Jun 30 '22 at 11:14
  • Of course Java `volatile` implies sequential-consistency, so incrementing a volatile means a sequentially-consistent store. On x86 that means a full barrier, about the same cost as a `lock add`. But on ARMv8.0 for example, AtomicInteger increment would need an `ldaxr` / `stlxr` retry loop, vs. volatile load / volatile store just needing a non-looping `ldar` (sequential-acquire load) / `stlr` (release store). https://godbolt.org/z/57nfTqEcr shows how the equivalent C would compile. More instructions doesn't always mean slower; separate atomic-load and atomic-store are like plain load/store. – Peter Cordes Jun 30 '22 at 11:23
  • An atomic increment is faster than taking a separate lock (`synchronized`) around a single increment, though. Locking means you can cheaply do multiple things to the same variable within one critical section, but if you only have one thing to do to one variable, atomic is great. – Peter Cordes Jun 30 '22 at 11:28