不断的学习,我们才能不断的前进
一个好的程序员是那种过单行线马路都要往两边看的人

CAS

compareAndSet 比较并交换: 比较当前工作内存中的值 和主内存中的值,如果这个值是期望的,那么执行替换,否则一直 循环(自旋锁)。

有点:自带原子性

缺点: 循环会耗时、一次只能保证一个共享变量、会出现ABA问题

public class TestCAS {
   @Test
   public void test(){
      AtomicInteger atomicInteger=new AtomicInteger(200);
      atomicInteger.compareAndSet(200,2001);
     atomicInteger.getAndIncrement(); // 加1
      System.out.println(atomicInteger.get());
      atomicInteger.compareAndSet(200,2002);
      System.out.println(atomicInteger.get());
   }
}

unsafe类

java通过这个unsafe类操作内存。自旋锁

public final int getAndAddInt(Object var1, long var2, int var4) {
    int var5;
    do {
        var5 = this.getIntVolatile(var1, var2); // 获取var1内存地址+var2偏移量的值
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));// var1+ var2 跟var5 比较,满足就替换var5 + var4
    return var5;
}

compareAndSwapInt是c++ native方法

ABA问题

比如两个线程都拿到同一个变量A=1,但是线程二把A的值改为3,再改回1。这个时候线程A拿到的1 是替换过后的1。

//ABA概述
@Test
public void test(){
   AtomicInteger atomicInteger=new AtomicInteger(200);

   // B线程,捣乱 200--》2001--》200
   atomicInteger.compareAndSet(200,2001);
   atomicInteger.compareAndSet(2001,200);
   System.out.println(atomicInteger.get());
   
   // 正常的A线程拿到的200,不是之前的200了
   atomicInteger.compareAndSet(200,2002);
   System.out.println(atomicInteger.get());
}

可通过乐观锁 加个版本号

AtomicStampedReference

@Test
public void testABA() throws InterruptedException {
   AtomicStampedReference<Integer> atomicStampedReference=new AtomicStampedReference<>(10,1);
   // a线程负责修改值 10--》11--》10
   new Thread(()->{
      int stamp = atomicStampedReference.getStamp();
      System.out.println("a1=>"+stamp);
      try {
         TimeUnit.SECONDS.sleep(1);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }
      System.out.println(atomicStampedReference.compareAndSet(10, 11,
            stamp, stamp + 1));
      System.out.println("a2=>"+atomicStampedReference.getStamp());

      System.out.println(atomicStampedReference.compareAndSet(11, 10,
            atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1));
      System.out.println("a2=>"+atomicStampedReference.getStamp());

   },"a").start();

   // b线程
   new Thread(()->{
      int stamp = atomicStampedReference.getStamp();
      System.out.println("b1=>"+stamp);
      try {
         TimeUnit.SECONDS.sleep(1);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }
      System.out.println(atomicStampedReference.compareAndSet(10, 66,
            stamp, stamp + 1));
      System.out.println("b2=>"+atomicStampedReference.getStamp());

   },"b").start();

   TimeUnit.SECONDS.sleep(3);
}

目录