简体   繁体   中英

What is the difference between Atomic Integer and Normal immutable Integer class in Java?

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.

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.

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

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.

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);

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. **

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM