In the java.util.concurrent.atomic
package after JDK1.5, there are more atomic processing classes.
- Primitive types: AtomicInteger, AtomicLong, AtomicBoolean;
- Array type: AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray;
- Reference types: AtomicReference, AtomicStampedRerence, AtomicMarkableReference;
- Object attribbutes modification types: AtomicIntegerFieldUpdater, AtomicLongFieldUpdater, AtomicReferenceFieldUpdater.
They are mainly used for efficient program processing in high concurrent environments to help us simplify synchronization processing.
The three primitive types of atomic classes: AtomicInteger
, AtomicLong
, and AtomicBoolean
, have similar principles and usage. This blog introduces the usage of primitive types of atomic classes with AtomicInteger
.
AtomicInteger
AtomicInteger
, an Integer
class that provides atomic operations. In the Java language, ++i
and i++
are not thread-safe, and when used, it is inevitable to use the synchronized
keyword. AtomicInteger
uses a thread-safe addition and subtraction operation interface.
Let’s take a look at what AtomicInteger
provides us:
1 | // get value |
Let’s look at the advantages of AtomicInteger through simple examples:
Normal thread synchronization
1 | class Test { |
Use AtomicInteger
1 | class Test { |
From the above example, we can see that using AtomicInteger
is thread safe. And because AtomicInteger
is implemented by hardware providing atomic operation instructions. In the absence of intense competition, the overhead is smaller and the speed is faster.
Let’s take incrementAndGet()
as an example to see how AtomicInteger
works.
1 | private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); |
Unsafe
is a class provided by java to gain access to the memory address of an object. It is actually an util in AtomicInteger
.
Value
is a variable used to store integers. It is declared as volatile
here to ensure that the current thread can get the latest value of the value during the update operation (in a concurrent environment, the value may have been updated by other threads).
The getAndAddInt()
method in Unsafe
class:
1 | public final int getAndAddInt(Object o, long offset, int delta) { |
It uses optimistic lock implementation: volatile
+ CAS
. If unsuccessful update, just continue the loop until success. The efficiency is much higher than lock(pessimistic lock) every time