In our previous post, we learnt about the volatile keyword in Java. But volatile keyword is not sufficient to guarantee atomicity. Volatility just guarantees the visibility of the variable and NOT atomicity, whereas Synchronization (locking) guarantees both visibility and atomicity.
But Synchronization affects processing time.
By visibility we mean that all the threads will get the latest form of the variable. In the above example, as you can see, all the threads get the latest value of counter in the subsequent reads.
AtomicInteger helps in getting the latest value of the last write by any given thread in a Multithreading environment. If we have multiple threads that reads and writes the integer, then AtomicInteger guarantees, the write operation must get the latest update from the memory.
AtomicIntegerExample.java - In this class, we have 2 variables, one is Integer and another is AtomicInteger. We have created 2 Threads that updates the values of both the fields by 1. This update operation is running 10000 times by 2 different threads. So final values expected for both the fields must be -
1) atomicInteger - 20000
2) integer - 20000
But since integer variable is just volatile, then multiple threads do not get the latest value during write. But that is taken care by the AtomicInteger as shown below -
package com.learning;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicIntegerExample implements Runnable {
@Override
public void run() {
int max = 10000;
for (int i = 0; i < max; i++) {
atomicInteger.addAndGet(1);
integer = integer + 1;
}
}
public static void main(String args[]) throws InterruptedException {
AtomicIntegerExample atomicIntegerExample = new AtomicIntegerExample();
atomicIntegerExample.setAtomicInteger(new AtomicInteger());
atomicIntegerExample.setInteger(new Integer(0));
Thread first = new Thread(atomicIntegerExample);
Thread second = new Thread(atomicIntegerExample);
// Threads start executing
first.start();
second.start();
// main thread will wait for both threads to complete execution
first.join();
second.join();
// Printing final value of count variable
System.out.println("Atomic Integer in Multithreading - " + atomicIntegerExample.getAtomicInteger());
System.out.println("Integer Value in Multithreading - " + atomicIntegerExample.getInteger());
}
private AtomicInteger atomicInteger;
private volatile Integer integer;
public AtomicInteger getAtomicInteger() {
return atomicInteger;
}
public void setAtomicInteger(AtomicInteger atomicInteger) {
this.atomicInteger = atomicInteger;
}
public Integer getInteger() {
return integer;
}
public void setInteger(Integer integer) {
this.integer = integer;
}
}
Output - Results of 5 different executions. Its clearly visible, AtomicInteger is safely incremented by 1 and all threads get the latest updates of the variable.
Atomic Integer in Multithreading - 20000
Integer Value in Multithreading - 11354
Atomic Integer in Multithreading - 20000
Integer Value in Multithreading - 11681
Atomic Integer in Multithreading - 20000
Integer Value in Multithreading - 12656
Atomic Integer in Multithreading - 20000
Integer Value in Multithreading - 11107
Atomic Integer in Multithreading - 20000
Integer Value in Multithreading - 13106
No comments:
Post a Comment