This is the 17th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

The JUC package provides a series of classes for atomic operations implemented using the non-blocking CAS algorithm, which provides a significant performance improvement over atomic operators implemented using locks. The JUC package contains AtomicInteger, AtomicLong, and AtomicBoolean, which work similarly. Let’s take AtomicLong as an example.

Let’s take a look at some of the source code:

public class AtomicLong extends Number implements java.io.Serializable {
    private static final long serialVersionUID = 1927816293512124184L; / / 1. AccessUnsafeThe class instanceprivate static final Unsafe unsafe = Unsafe.getUnsafe(a); / / 2. StorevalueThe offsetprivate static final long valueOffset;
    static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8(a); //3. Used to check whether support is supportedLongType unlockedCAS
    private static native boolean VMSupportsCS8(a);static {
        try{/ / 4valueinAtomicLongOffset invalueOffset = unsafe.objectFieldOffset
                (AtomicLong.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }} //5. Actual variable valuesprivate volatile long value; / * * *Creates a new AtomicLong with the given initial value.
     *
     * @param initialValue the initial value* /public AtomicLong(long initialValue) {
        value = initialValue; } ······ omit part of code ············· ···Copy the code

In the Unsafe code above, an instance of the Unsafe class is obtained in code 1 via safe.getunsafe () (since the AtomicLong class is under the rt.jar package, the AtomicLong class is loaded through the Bootstarp classloader). At code 5, value is declared as volatile to ensure memory visibility. Get the offset of the value variable in the AtomicLong class in code 2,4.

Here are the main functions in AtomicLong:

  1. Increment and decrement codes
// after calling the unsafe method and setting value=value+1, Public Final Long getAndIncrement() {return unsafe. GetAndAddLong (this, valueOffset, 1L); } // after calling the unsafe method and setting value=value-1, Public Final Long getAndDecrement() {return insecure. GetAndAddLong (this, valueOffset, -1L); } // after calling the unsafe method and setting value=value+1, Public Final Long incrementAndGet() {return unsafe. GetAndAddLong (this, valueOffset, 1L) + 1L; } // after calling the unsafe method and setting value=value-1, DecrementAndGet () public Final Long decrementAndGet() {return unsafe. GetAndAddLong (this, valueOffset, -1l) -1l; }Copy the code

The Unsafe getAndAddLong method is an atomic operation, where the first argument is the reference to the AtomicLong instance and the second argument is the offset value of the AtomicLong variable. The third argument is the value of the second variable to set.

Where getAndIncrement() is implemented in JDK7 as follows:

public final long getAndIncrement(a) {
    while(true) {
        long current = get();
        long next = current + 1;
        if (compareAndSet(current, next))
            returncurrent; }}Copy the code

In the code above, each thread takes the current value of the variable, incrementing it in working memory by one, and changing the value of the variable using CAS. If the setting fails, the loop continues until the setting succeeds.

The logic in JDK8 is:

public final long getAndIncrement(a) {
        retrturn unsafe.getAndAddLong(this, valueOffset, 1L);
    }
Copy the code

Unsafe. getAndAddLong ();

public final long getAndAddLong(Object var1, long var2, long var4) {
   long var6;
   do {
       var6 = this.getLongVolatile(var1, var2);
   } while(!this.compareAndSwapLong(var1, var2, var6, var6 + var4));

   return var6;
}
Copy the code

As you can see, the loop logic in AtomicLong in JDK7 was already built into the atomic operations class Unsafe in JDK8.

  1. boolean compareAndSet(long expect,long update)
public final boolean compareAndSet(long expect,long update) 
{
    return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
}
Copy the code

Function in the internal call the unsafe.com pareAndSwapLong method. If the value in the atomic variable is equal to expect, it is updated with the update value and returns true, otherwise false is returned.