In this tutorial, we will discuss Atomic in Java, its operations, classes, and variables with detailed examples.
Table of Contents
Atomic in Java
Atomic in Java is a very important concept in a multithreading environment. It is one of the concurrent utilities that ensure multiple threads use the shared resources effectively without leading to any issues. This is because these shared resources can change their values during execution in a multithreaded environment. We can implement atomicity in classes, operations, and variables.
Java Atomic classes
The atomic classes are present in the java.util.concurrent.atomic
package. It provides lock-free and thread-safe implementation on a shared variable. It also supports atomic operations. The atomic classes have get()
and set()
methods that are used to read and write the volatile variables.
Below are the different sets of atomic classes present in the concurrent package.
Atomic class | Description |
---|---|
AtomicBoolean | Updates the boolean values atomically |
AtomicInteger | Updates the integer values atomically |
AtomicIntegerArray | Updates the integer array elements atomically |
AtomicLong | Updates the long values atomically |
AtomicLongArray | Updates the long array elements atomically |
AtomicMarkableReference | Updates the object reference with a mark bit atomically |
AtomicReference | Updates the object reference atomically |
AtomicArrayReference | Updates the array of object reference atomically |
Below are the common methods that are part of the atomic classes
get(): Retrieves the current value
set(): Sets the value of the atomic variable
lazySet(): Eventually sets the value of the atomic variable
compareAndSet(): Sets the value to the updated value if it is equal to the expected value.
Java Atomic operations
Atomic operations or actions that execute together or never execute at all. Below are the three main concepts with respect to atomic operations.
- Atomic operations may be invisible or undefined and unpredictable.
- Visible actions occur when the effect of one thread is visible to the other thread.
- Ordering of actions can occur when the actions in the thread are out of order for the other thread.
We can implement atomic actions by any of the below:
- Volatile variables
- Low-level atomic operations(unsafe)
- Atomic classes
Java Atomic variables
We can use atomic variables to perform atomic operations on a variable. It is important to use these variables in a multithreaded environment else it might lead to concurrency issues.
Example: Atomic variable
Below is an example of using an atomic variable in a multithreading environment. This is thread-safe since we are using the counter as an atomic variable and prevents inconsistent results when multiple threads use the same variable. The addAndGet()
method increments the value and then retrieves it. Since both operations are performed together, it is atomic in nature and does not affect the results even when there are multiple threads accessing it.
import java.util.concurrent.atomic.*; class UpdateCounter extends Thread { AtomicInteger aiCount; UpdateCounter(){ aiCount = new AtomicInteger(); } public void run() { int max = 10; for(int i=0;i<max;i++) aiCount.addAndGet(1); } } public class AtomicDemo { public static void main(String[] args) throws InterruptedException { UpdateCounter c = new UpdateCounter(); Thread t1 = new Thread(c, "Thread1"); Thread t2 = new Thread(c, "Thread2"); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println(c.aiCount); } }
20
Difference between Atomic, Synchronized and volatile
Atomic | Synchronized | Volatile |
---|---|---|
Applies to variables | Applies to methods | Applies to variables |
Ensures visibility along with atomicity | Ensures visibility along with atomicity | Ensures only visibility and no atomicity |
Not Applicable | Can implement any synchronized block or method | Not applicable |
Not applicable | Can lock the same object or different object | Not applicable |