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.
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.
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.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
Hi Sir, if we want to run the count by input int x (Scanner). How to pass the int x to another class?
- Ramesh
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(); }
- Rahul
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
- Salil Misra
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
- Rakesh Agarwal
Can we use instead of AtomicInteger, CountDownLatch for the multithread environment?
- Vimal Panchal
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
- Prakash
Great Job Pankaj . Blogs are very simple and helpful .
- Radhika Sharma
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
- ashu
I think we need better explanation, not just the syntax on how to use AtomicInteger, its available everywhere else on the internet.
- Prashant
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.
- Nitin