Today we will look into AtomicInteger
in Java. Atomic operations are performed in a single unit of task without interference from other operations. Atomic operations are necessity in multi-threaded environment to avoid data inconsistency.
Table of Contents
AtomicInteger
Let’s create a simple multi-threaded program where every thread increments the shared count
variable 4 times. So if there are two threads, after they finish count
value should be 8.
JavaAtomic.java
package com.journaldev.concurrency;
public class JavaAtomic {
public static void main(String[] args) throws InterruptedException {
ProcessingThread pt = new ProcessingThread();
Thread t1 = new Thread(pt, "t1");
t1.start();
Thread t2 = new Thread(pt, "t2");
t2.start();
t1.join();
t2.join();
System.out.println("Processing count=" + pt.getCount());
}
}
class ProcessingThread implements Runnable {
private int count;
@Override
public void run() {
for (int i = 1; i < 5; i++) {
processSomething(i);
count++;
}
}
public int getCount() {
return this.count;
}
private void processSomething(int i) {
// processing some job
try {
Thread.sleep(i * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
If you will run above program, you will notice that count
value varies between 5,6,7,8. The reason is because count++ is not an atomic operation. So by the time one threads read it’s value and increment it by one, other thread has read the older value leading to wrong result.
To solve this issue, we will have to make sure that increment operation on count is atomic, we can do that using Synchronization but Java 5 java.util.concurrent.atomic
provides wrapper classes for int and long that can be used to achieve this atomic operation without usage of Synchronization.
Java AtomicInteger Example
Here is the updated program that will always output count value as 8 because AtomicInteger
method incrementAndGet()
atomically increments the current value by one.
package com.journaldev.concurrency;
import java.util.concurrent.atomic.AtomicInteger;
public class JavaAtomic {
public static void main(String[] args) throws InterruptedException {
ProcessingThread pt = new ProcessingThread();
Thread t1 = new Thread(pt, "t1");
t1.start();
Thread t2 = new Thread(pt, "t2");
t2.start();
t1.join();
t2.join();
System.out.println("Processing count=" + pt.getCount());
}
}
class ProcessingThread implements Runnable {
private AtomicInteger count = new AtomicInteger();
@Override
public void run() {
for (int i = 1; i < 5; i++) {
processSomething(i);
count.incrementAndGet();
}
}
public int getCount() {
return this.count.get();
}
private void processSomething(int i) {
// processing some job
try {
Thread.sleep(i * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Benefits of using Concurrency classes for atomic operation is that we don’t need to worry about synchronization. This improves code readability and chance of errors are reduced. Also atomic operation concurrency classes are assumed to be more efficient that synchronization which involves locking resources.
public class AtomicOperations implements Runnable{
AtomicInteger ai = new AtomicInteger(1);
int count = 10;
@Override
public void run(){
while(ai.get()<= count){
if(ai.get() % 2 == 0 && Thread.currentThread().getName().equals("Even")){
System.out.println(Thread.currentThread().getName() + " " + ai.getAndIncrement());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else if(ai.get() % 2 != 0 && Thread.currentThread().getName().equals("Odd")){
System.out.println(Thread.currentThread().getName() + " " + ai.getAndIncrement());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main(String args[]) throws InterruptedException{
AtomicOperations obj = new AtomicOperations();
Thread t1 = new Thread(obj, "Even");
Thread t2 = new Thread(obj, "Odd");
t1.start();
t2.start();
}
IMO the example you took above does not satisfy the issue of atomicity. Though there is no issue with example per se for AtomicInteger but the use case that you have used is not a fit here.
Let me know if I am wrong.
~ Salil
Hi Sir,
I am getting inconsistent result although i am using AtomicInteger,Can you help me out.
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadTest implements Runnable {
AtomicInteger i=new AtomicInteger();
public static void main(String[] args) {
Thread test=new Thread(new ThreadTest());
test.start();
test.run();
}
@Override
public void run() {
// TODO Auto-generated method stub
i.incrementAndGet();
System.out.println(Thread.currentThread().getName() +”: ” + i.get());
}
}
Expected Outup: each time the output should be 1 2
Can we use instead of AtomicInteger, CountDownLatch for the multithread environment?
Thanks for the nice and valuable article Pankaj !!!
Can you share any idea on how to ensure consistency and thread safe for a String shared by multiple threads.
Or do I need to use any other dataType for TEXT type ???
Thanks in advance
String is immutable, so it’s thread-safe. You can use it in the multithreaded environment.
Great Job Pankaj . Blogs are very simple and helpful .
Hello Sir
I understand the concept but there is one thing I am failing to understand. If i remove the processSomething(i) call, then every time i am getting the count=8. I tried for almost 20 times but every time got perfect 8.
Can you please explain why
I think i got the reason, If i increase the loop from 4 to say 5000 then i am get the expected result(somthing between 5000 and 10000). I think 4 is to small a count , whenever a thread will get some cpu time it will be able to increase the counter by 4.
I think we need better explanation, not just the syntax on how to use AtomicInteger, its available everywhere else on the internet.
This is a wrong explanation u r joining both threads . Did not expect this dumb kind of explanation from such a senior analyst.
Clear ur concepts first.
Thanks for calling me a senior analyst. And what is the problem with join()? It’s used so that main method finishes after both the threads and we can simulate the problem.
I think t1.join() will block other threads until t1 is terminated and then t2.join() will block other threads until t2 completes. In this case threads will run sequentially t1 then t2 then main thread.
So, join should not be there in this explanation. Correct me if I am wrong.
No you didn’t understand join() method. When you add some log in the ProcessingThread like
System.out.printf(“%s: %d\n”,Thread.currentThread().getName(),this.getCount()) you will understand better;
You are right.
I think that Thread.sleep(i * 1);, So thread main, t1 and t2 are running parallel. .
if don’t use Thread.sleep(); So t1 and t2 are running order;
Clear you concepts first. And before that clear your concepts of how to talk in comments section. knowledge is give and take relationship. Why so angry if you know something.
well said
He has called the join after issuing the start command on both the threads. The subsequent joins will pause the main thread until t1 and t2 are complete. Why do you think they would be sequential
I don’t see any issue with the example. Thread main, t1 and t2 are running parallel. Check when start() method is called. t1.join() makes main thread to wait for t1’s completion and then t2.join() makes main thread to wait for t2’s completion. It’s not like t1 and t2 are not running parallel. Definitely t1 and t2 are running parallel.
Very nice Pankaj for this article.
t1.join();t2.join(); will make run in parallel. you can put sop in code and debug. Thanks Pankaj. great tutorial.
I think the count value going “5,6,7,8” is perfectly acceptable in your first example isn’t it?
But Yes. I got the concept.
I think the count value will be always 8.
it’s very usefully for me ,this is my first time visited this site.The tutorials understandability,thanks a lot.But i didn’t understand how to use Atomic integer class?
Good site for java interview preparation. But i didn’t understand why to use Atomic integer class. Can you please provide the scenario where we can use this
Hi,
Simply i can modify the program you suggested above for atomic but i haven’t seen any benefit of this atomic variable because in both cases i am getting same result. So can you please provide another example for the same to see what exactly it is..
package test;
import java.util.concurrent.atomic.AtomicInteger;
public class JavaAtomic {
public static void main(String[] args) throws InterruptedException {
ProcessingThread pt = new ProcessingThread();
Thread t1 = new Thread(pt, “t1”);
Thread t2 = new Thread(pt, “t2”);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(“Processing count=” + pt.getCount());
}
}
class ProcessingThread implements Runnable {
// private AtomicInteger count = new AtomicInteger();
int count = 0;
@Override
public void run() {
// count.incrementAndGet();
for (int i = 0; i < 4; i++) {
count++;
}
}
public int getCount() {
// return this.count.get();
return count;
}
}
Yeah its late reply, but will help others.
try to put a sleep(100) in run method, and run your program 8~10 times again & again, you will get it.
Also @Pankaj, Thanks a lot for such great tutorials, Journaldev is best among others. Great work
How is atomicity incorporated into the Atomic Integer class? it has to be via locks right ?? Then how is this different from Synchronisation block?
Yes internally it must be using locks but because Java provides guarantee of atomic operations, we don’t need to implement it ourself, this is the plus point.
I dont think its using locks since synchronization reduces the throughput of the execution and AtomicIntegers are used in lock-free implementation.
Internally Atomic integer is volatile integer. Through Volatility, it is providing Atmicity.
Every read and write operation happens from memory,
Not true IMO. Atomic Integers are more Thread Safer than volatile variables. volatile guarantees only the exact value at any point, but does not guarantee thread safety. meaning to say since ++ operation internally involves 2 operations 1 for reading other for doing +1. Using volatile in multi-threaded scenario will result in race condition.
Explanation : when Thread 1 calls ++ first it reads the volatile variable value (assume value is 2) since ++ is two operation , before even the first Thread increment the value second Thread reads the volatile variable value (at this point value is still 2) now first 1 incremented value from 2 to 3, and second Thread also does the same as the value was 2 when second the Thread read it. Finally the result would be 3, but expected is 4.
Thanks a lot this tutorial.
nice blog sir…thanks a lot…
Thank you very much for your site and tutorials!
You are doing very great job, even after almost 7 years in java development i can find something new in your blog posts!
Thank you very much and good luck!