Compréhension approfondie des références CAS et atomiques
Une compréhension approfondie de CAS
Qu'est-ce que CAS
ublic class CASDemo {
//CAS compareAndSet:比较并交换
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(2020);
// 期望、更新
// public final boolean compareAndSet(int expect, int update)
// 如果我期望的值达到了,那么就更新,否则,就不更新, CAS 是CPU的并发原语!
// ============== 捣乱的线程 ==================
System.out.println(atomicInteger.compareAndSet(2020,2021));
System.out.println(atomicInteger.get());
//atomicInteger.getAndIncrement();
System.out.println(atomicInteger.compareAndSet(2021,2020));
System.out.println(atomicInteger.get());
// ============== 期望的线程 ==================
System.out.println(atomicInteger.compareAndSet(2020,6666));
System.out.println(atomicInteger.get());
}
}
classe dangereuse
Mémoire d'opération de mot derrière la figure ci-dessus
CAS: Comparez la valeur de la mémoire de travail actuelle avec la valeur de la mémoire principale, si cette valeur est attendue, alors effectuez l'opération! Si ce n'est pas le cas, continuez à boucler!
Désavantages:
1. Le cycle prendra du temps
2. Une seule fois peut garantir l'atomicité d'une variable partagée
3. Problème ABA
CAS: problème ABA (civette chat pour prince)
public class CASDemo {
// CAS compareAndSet 比较并交换
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(2020);
// 期望、更新
// public final boolean compareAndSet(int expect, int update)
// 如果期望得值成功了,那么就更新,否则就不更新 CAS是CPU的并发原语。
// ============== 捣乱的线程 ==================
System.out.println(atomicInteger.compareAndSet(2020, 2021));
System.out.println(atomicInteger.get());
System.out.println(atomicInteger.compareAndSet(2021, 2020));
System.out.println(atomicInteger.get());
// ============== 期望的线程 ==================
System.out.println(atomicInteger.compareAndSet(2020, 6666));
System.out.println(atomicInteger.get());
}
}
2. Citation atomique
Résolvez le problème ABA et introduisez des références atomiques! Pensée correspondante: verrouillage optimiste!
Fonctionnement atomique avec numéro de version!
public class CASDemo {
// AtomicStampedReference 注意,如果泛型是一个包装类,注意对象的引用问题,范围内用同一个,超出自动new新的
// 正常在业务操作,这里面比较的都是一个个对象
static AtomicStampedReference<Integer> atomicStampedReference = new
AtomicStampedReference<>(1, 1);
// CAS compareAndSet : 比较并交换!
public static void main(String[] args) {
new Thread(() -> {
int stamp = atomicStampedReference.getStamp(); // 获得版本号
System.out.println("a1=>" + stamp);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
atomicStampedReference.compareAndSet(1, 2,
atomicStampedReference.getStamp(),
atomicStampedReference.getStamp() + 1);
System.out.println("a2=>" + atomicStampedReference.getStamp());
System.out.println(atomicStampedReference.compareAndSet(2, 1,
atomicStampedReference.getStamp(),
atomicStampedReference.getStamp() + 1));
System.out.println("a3=>" + atomicStampedReference.getStamp());
}, "a").start();
// 乐观锁的原理相同!
new Thread(() -> {
int stamp = atomicStampedReference.getStamp(); // 获得版本号
System.out.println("b1=>" + stamp);
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(atomicStampedReference.compareAndSet(1, 6,
stamp, stamp + 1));
System.out.println("b2=>" + atomicStampedReference.getStamp());
}, "b").start();
}
}
Remarque:
Integer utilise le mécanisme de mise en cache des objets, la plage par défaut est -128 ~ 127, il est recommandé d'utiliser la méthode de fabrique statique valueOf pour obtenir des instances d'objet au lieu de new, car valueOf utilise la mise en cache, et new créera certainement de nouveaux objets et allouera une nouvelle mémoire espace;