Werfen wir zunächst einen Blick auf einen Teil des Quellcodes:
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; } ············省略部分代码············· }
Im obigen Code wird die Instanz der Unsafe-Klasse über Unsafe.getUnsafe() bei Code 1 abgerufen (da die AtomicLong-Klasse unter der rt. jar-Paket und die AtomicLong-Klasse wird übergeben und vom Bootstarp-Klassenlader geladen). Bei Code 5 wird der Wert als flüchtiger Typ deklariert, um die Sichtbarkeit des Speichers sicherzustellen. Ermitteln Sie den Offset der Wertvariablen in der AtomicLong-Klasse über die Codes 2 und 4.
Als nächstes stellen wir die Hauptfunktionen in AtomicLong vor:
Inkrement- und Dekrementierungscode
//调用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; }
Die oben genannten vier Funktionen werden intern durch Aufrufen der getAndAddLong-Methode von Unsafe implementiert. Diese Funktion ist eine atomare Operation ein Verweis auf die AtomicLong-Instanz, der zweite Parameter ist der Offset-Wert der Wertvariablen in AtomicLong und der dritte Parameter ist der Wert der zweiten festzulegenden Variablen.
Die Implementierungslogik der getAndIncrement()-Methode in JDK7 lautet:
public final long getAndIncrement() { while(true) { long current = get(); long next = current + 1; if (compareAndSet(current, next)) return current; } }
Im obigen Code erhält jeder Thread zuerst den aktuellen Wert der Variablen (da der Wert eine flüchtige Variable ist, ist dies also der zuletzt erhaltene Wert). und dann im Arbeitsspeicher um 1 erhöhen und dann den Wert der Variablen mit CAS ändern. Wenn die Einstellung fehlschlägt, versucht die Schleife weiter, bis die Einstellung erfolgreich ist.
Die Logik in JDK8 lautet:
public final long getAndIncrement() { retrturn unsafe.getAndAddLong(this, valueOffset, 1L); }
Der Code von unsafe.getAndAddLong in JDK8 lautet:
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; }
Es ist ersichtlich, dass die Schleifenlogik in AtomicLong in JDK7 durch die atomare Operationsklasse Unsafe in ersetzt wurde JDK8 Eingebaut. Die Funktion
Boolean CompareAndSet(long Expect, Long Update)
public final boolean compareAndSet(long expect,long update) { return unsafe.compareAndSwapLong(this, valueOffset, expect, update); }
ruft intern die Methode unsafe.compareAndSwapLong auf. Wenn der Wert in der atomaren Variablen dem erwarteten Wert entspricht, aktualisieren Sie den Wert mithilfe des Aktualisierungswerts und geben Sie „true“ zurück, andernfalls geben Sie „false“ zurück.
Das obige ist der detaillierte Inhalt vonAnalyse des Quellcodes der Java-Atomic-Operationsklasse. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!