AtomicLong class in Java provides a long value that may be updated atomically. This class resides in the java.util.concurrent.atomic package which has classes that support lock-free thread-safe programming on single variables. Apart from AtomicLong some of the other classes are AtomicInteger, AtomicReference, DoubleAccumulator.
The atomic variable classes in Java concurrency like AtomicLong, AtomicInteger use non-blocking algorithm. These non-blocking algorithms use low-level atomic machine instructions such as compare-and-swap instead of locks to ensure data integrity under concurrent access.
Classes in this package java.util.concurrent.atomic provides methods that can get, set or compare value as an atomic operation i.e. without any interruption. There is no need to explicitly use any locking or synchronization.
Java AtomicLong Constructor
Java AtomicLong class has two constructors-
- AtomicLong()- Creates a new AtomicLong with initial value 0.
- AtomicLong(long initialValue)- Creates a new AtomicLong with the given initial value.
Atomic operations
AtomicLong class provides atomic methods for getting, setting, incrementing and decrementing variables like getAndIncrement(), getAndDecrement(), decrementAndGet(), getAndSet(), getAndAdd() etc.
From the method names itself you can easily deduce that these are atomic methods as example if you take getAndIncrement() method which is doing three operations.
Gets the value Increment the value by 1 Sets the updated value back
But these 3 operations are done as a single unit i.e. atomic operation. Either all 3 succeed or none.
There is also a compareAndSet(int expect, int update) method which atomically sets the value to the given updated value if the current value == the expected value.
AtomicLong Java Example Code
Let us see some examples using AtomicLong.
1. Methods to add to the AtomicLong
Some of the methods that can be used for adding are
- addAndGet(long delta)- Atomically adds the given value to the current value. Returns the updated value.
- getAndAdd(long delta)- Atomically adds the given value to the current value. Returns the previous value.
- incrementAndGet()- Atomically increments the current value by one. Returns the updated value.
- getAndIncrement()- Atomically increments by one the current value. Returns the previous value.
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; public class AtomicLongDemo { public static void main(String[] args) { AtomicLong al = new AtomicLong(); ExecutorService ex = Executors.newFixedThreadPool(2); ex.execute(new IncTask(al)); ex.execute(new IncTask(al)); ex.execute(new IncTask(al)); ex.execute(new IncTask(al)); } } class IncTask implements Runnable{ AtomicLong al = null; IncTask(AtomicLong al){ this.al = al; } @Override public void run() { System.out.println("Value - " + al.getAndIncrement() + " for " + Thread.currentThread().getName()); } }
Output
Value - 1 for pool-1-thread-2 Value - 0 for pool-1-thread-1 Value - 2 for pool-1-thread-2 Value - 3 for pool-1-thread-1
In this code if you notice there is no synchronization or ReentrantLock is used still values are different for different threads as AtomicLong is used. You can change AtomicLong to just Long and see how the same program behaves.
2. addAndGet and getAndAdd() methods
As already mentioned addAndGet() method returns the updated value whereas getAndAdd() returns the previous value.
import java.util.concurrent.atomic.AtomicLong; public class AddAtomicLong { public static void main(String[] args) { AtomicLong al = new AtomicLong(); System.out.println("Value after addAndGet - " + al.addAndGet(7)); System.out.println("Value after getAndAdd - " + al.getAndAdd(7)); System.out.println("Current Value - " + al.get()); } }
Output
Value after addAndGet - 7 Value after getAndAdd - 7 Current Value - 14
3. compareAndSet() method
compareAndSet(long expect, long update)- Atomically sets the value to the given updated value if the current value == the
expected value.
Returns true if successful. False return indicates that the actual value was not equal to the expected value.
Example code
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; public class AddAtomicLong { public static void main(String[] args) { AtomicLong al = new AtomicLong(7); ExecutorService ex = Executors.newFixedThreadPool(2); ex.execute(new CompareTask(al)); ex.execute(new CompareTask(al)); ex.execute(new CompareTask(al)); ex.execute(new CompareTask(al)); ex.shutdown(); System.out.println("Current Value " + al.get()); } } class CompareTask implements Runnable{ AtomicLong al = null; CompareTask(AtomicLong al){ this.al = al; } @Override public void run() { System.out.println("Value - " + al.compareAndSet(7, 3) + " for " + Thread.currentThread().getName()); } }
Output
Current Value 3 Value - true for pool-1-thread-1 Value - false for pool-1-thread-2 Value - false for pool-1-thread-1 Value - false for pool-1-thread-2
Here it can be seen that when compareAndSet() method is called for these 4 threads, only one thread will be able to set the value to 3. After that all the other will return false as expected value becomes 3.
That's all for this topic AtomicLong in Java With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!
Related Topics
You may also like-