Jetons d'abord un coup d'œil à une partie du code source :
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; } ············省略部分代码············· }
Dans le code ci-dessus, l'instance de la classe Unsafe est obtenue via Unsafe.getUnsafe() au code 1 (car la classe AtomicLong est sous le rt. jar et la classe AtomicLong est transmise (chargée par le chargeur de classe Bootstarp). Au code 5, la valeur est déclarée comme type volatile pour garantir la visibilité de la mémoire. Obtenez le décalage de la variable de valeur dans la classe AtomicLong via les codes 2 et 4.
Ensuite, présentons les principales fonctions d'AtomicLong :
Code d'incrémentation et de décrémentation
//调用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; }
Les quatre fonctions ci-dessus sont implémentées en interne en appelant la méthode getAndAddLong de Unsafe. Cette fonction est une opération atomique. Le premier paramètre ici est. une référence à l'instance AtomicLong, le deuxième paramètre est la valeur de décalage de la variable de valeur dans AtomicLong et le troisième paramètre est la valeur de la deuxième variable à définir.
La logique d'implémentation de la méthode getAndIncrement() dans JDK7 est la suivante :
public final long getAndIncrement() { while(true) { long current = get(); long next = current + 1; if (compareAndSet(current, next)) return current; } }
Dans le code ci-dessus, chaque thread obtient d'abord la valeur actuelle de la variable (puisque la valeur est une variable volatile, il s'agit donc de la dernière valeur obtenue), puis incrémentez-le de 1 dans la mémoire de travail, puis utilisez CAS pour modifier la valeur de la variable. Si le paramètre échoue, la boucle continue d'essayer jusqu'à ce que le paramètre réussisse.
La logique dans JDK8 est :
public final long getAndIncrement() { retrturn unsafe.getAndAddLong(this, valueOffset, 1L); }
Le code de unsafe.getAndAddLong dans JDK8 est :
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; }
On peut voir que la logique de boucle dans AtomicLong dans JDK7 a été remplacée par la classe d'opération atomique Unsafe dans JDK8 intégré. La fonction
boolean compareAndSet(long wait, long update)
public final boolean compareAndSet(long expect,long update) { return unsafe.compareAndSwapLong(this, valueOffset, expect, update); }
appelle la méthode unsafe.compareAndSwapLong en interne. Si la valeur de la variable atomique est égale à celle attendue, mettez à jour la valeur en utilisant la valeur de mise à jour et renvoyez vrai, sinon renvoyez faux.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!