Normally we would lock if we wanted to avoid atomic problems, but we all know that locking and unlocking costs money. And as long as the lock, unlock will be accompanied by thread blocking, thread wake up, such thread switching is also a performance cost.

Atomic classes have been available since JDK1.5 to avoid atomicity problems without locking, so in simple cases where only one shared variable is competing, you can use Java atomic classes. If multiple shared variables are competing, you can only lock atomic classes. Java atomic classes can be divided into five categories: atomic update primitive types, atomic update arrays, atomic update reference types, atomic update attributes (fields of the class), and atomic accumulators. How do they achieve atomicity without locking? No big secret is hardware support! We know that CPU instructions must be atomic, and to solve the concurrency problem the CPU provides a CAS(compare and swap) instruction.

The CAS instruction contains three parameters: A, the memory address of the shared variable, B, the value used for comparison, and C, the new value of the shared variable. The value of address A can be changed to C only if the value of address A in memory is equal to B.

If the expected value B is equal to the value in the memory address A, the shared variable has not been modified by other threads, so new values are allowed to update.

CAS also has ABA problems, which is that when you compare, maybe your value is changed by one thread, and then changed back by another thread, and then you compare and find out that the value was changed as expected. It’s like when you walk down the street, you put your phone in your pocket, and the thief steals your phone, but then he looks up and sees the camera overhead and silently puts it back in your pocket. You don’t know it’s happening, and then you pick up your phone, check moments, and stuff it in your pocket…

In most cases you don’t need to worry about this, such as primitive types, but atomic update reference types, because one of the attributes in them may have changed while comparing threads. You can add a version number to avoid this problem.

The most common way to solve concurrency problems with CAS is through spin, where the spin is actually trying to loop, and to be more specific, the while loop. For example, the AtomicInteger source code declares private volatile int value; Visibility is guaranteed by the volatile keyword.

public final int getAndIncrement() {
   return unsafe.getAndAddInt(this, valueOffset, 1);
}

public final int getAndAddInt(Object var1, long var2, int var4) {
   int var5;
   do{ var5 = this.getIntVolatile(var1, var2); // read the value in memory}while(! this.compareAndSwapInt(var1, var2, var5, var5 + var4)); // If the expected values do not match, read the values in memory again for comparisonreturn var5;
}

public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
Copy the code

Atomic classes are implemented by calling sun.misc.Unsafe, as in the above code, which calls unsafe.getAndAddInt(). Do while is spin, compareAndSwapInt is native.

All atomic class implementations basically follow this idea! The Java concurrency package helps us encapsulate it, making it easier for us to call!

Atomic update base type

Related implementation classes: AtomicBoolean, AtomicInteger, AtomicLong. This is primarily used for basic types of operations

Atomic update array type

Related implementation classes: AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray. You can update every element in an array atomically, and the difference from atomic update is that basically the method has an array index.

Atomic update reference types

Related implementation classes: AtomicReference, AtomicStampedReference, AtomicMarkableReference. This will focus on ABA, but Java already does so so AtomicStampedReference and AtomicMarkableReference will avoid ABA problems by using version numbers!

Atomic update field type

Related implementation classes: AtomicIntegerFieldUpdater, AtomicLongFieldUpdater, AtomicReferenceFieldUpdater they atomization to update the object’s properties, Note that fields (attributes) of the updated class must use the public volatile modifier to ensure visibility.

Atomic accumulator

Related implementation classes: LongAccumulator, LongAdder, DoubleAccumulator, DoubleAdder. These classes can only be used for accumulative operations, but they are better for atomic update base types, so they can be used for accumulative operations only!


If wrong welcome to correct! Personal public account: Yes training level guide