Let’s take a look at part of the source code first:
public class AtomicLong extends Number implements java.io.Serializable { private static final long serialVersionUID = 1927816293512124184L; //1.获取Unsafe类实例 private static final Unsafe unsafe = Unsafe.getUnsafe(); //2.存放value的偏移量 private static final long valueOffset; static final boolean VM_SUPPORTS_LONG_CAS = VMSupportsCS8(); //3.用于判断是否支持Long类型无锁CAS private static native boolean VMSupportsCS8(); static { try { //4.获取value在AtomicLong中的偏移量 valueOffset = unsafe.objectFieldOffset (AtomicLong.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } } //5.实际变量值 private volatile long value; /** * Creates a new AtomicLong with the given initial value. * * @param initialValue the initial value */ public AtomicLong(long initialValue) { value = initialValue; } ············省略部分代码············· }
In the above code, the instance of the Unsafe class is obtained through Unsafe.getUnsafe() at code 1 (because the AtomicLong class is in rt Under the .jar package, the AtomicLong class is loaded through the Bootstarp class loader). At code 5, value is declared as volatile type to ensure memory visibility. Get the offset of the value variable in the AtomicLong class through codes 2 and 4.
Next, let’s introduce the main functions in AtomicLong:
Increment and decrement code
//调用unsafe方法,设置value=value+1后,返回原始的值 public final long getAndIncrement() { return unsafe.getAndAddLong(this, valueOffset, 1L); } //调用unsafe方法,设置value=value-1后,返回原始的值 public final long getAndDecrement() { return unsafe.getAndAddLong(this, valueOffset, -1L); } //调用unsafe方法,设置value=value+1后,返回递增后的值 public final long incrementAndGet() { return unsafe.getAndAddLong(this, valueOffset, 1L) + 1L; } //调用unsafe方法,设置value=value-1后,返回递减后的值 public final long decrementAndGet() { return unsafe.getAndAddLong(this, valueOffset, -1L) - 1L; }
The above four functions The operation is implemented internally by calling Unsafe's getAndAddLong method. This function is an atomic operation. The first parameter here is a reference to the AtomicLong instance. The second parameter is the offset value of the value variable in AtomicLong. The third parameter is is the value of the second variable to be set.
The implementation logic of the getAndIncrement() method in JDK7 is:
public final long getAndIncrement() { while(true) { long current = get(); long next = current + 1; if (compareAndSet(current, next)) return current; } }
In the above code, each thread first gets the current value of the variable (since value is a volatile variable, so this is The latest value obtained), then increment it by 1 in the working memory, and then use CAS to modify the value of the variable. If the setting fails, the loop continues to try until the setting is successful.
The logic in JDK8 is:
public final long getAndIncrement() { retrturn unsafe.getAndAddLong(this, valueOffset, 1L); }
The code of unsafe.getAndAddLong in JDK8 is:
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; }
From It can be seen that the loop logic in AtomicLong in JDK7 has been built into the atomic operation class Unsafe in JDK8.
boolean compareAndSet(long expect, long update)
public final boolean compareAndSet(long expect,long update) { return unsafe.compareAndSwapLong(this, valueOffset, expect, update); }
The function calls the unsafe.compareAndSwapLong method internally. If the value in the atomic variable is equal to expect, update the value using the update value and return true, otherwise return false.
The above is the detailed content of Java atomic operation class source code analysis. For more information, please follow other related articles on the PHP Chinese website!