Skip to content
DAILY QUOTE

“ ”

解决ABA问题,引入原子引用!对应的思想:乐观锁!

带版本号的原子操作!

java
package com.mystpet.dianli;  
  
import java.util.concurrent.TimeUnit;  
import java.util.concurrent.atomic.AtomicStampedReference;  
  
public class CASBAB {  
    public static void main(String[] args) {  
  
        // AtomicStampedReference  注意,如果泛型是一个包装类,注意对象的引用问题  
  
        // 正常在业务操作中,这里面比较的都是一个个对象  
        // integer默认缓存-128->127,超过这个范围就要new对象了,就会分配新的地址,我们看到源码是==,非数值类型,我们比较的是对象的地址  
  
        AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(1, 1);  
  
        new Thread(()->{  
            int stamp=atomicStampedReference.getStamp();  
            System.out.println("a1=>"+stamp);  
  
            try {  
                TimeUnit.SECONDS.sleep(1);  
            } catch (InterruptedException e) {  
                throw new RuntimeException(e);  
            }  
  
            System.out.println(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) {  
                throw new RuntimeException(e);  
            }  
  
            System.out.println(atomicStampedReference.compareAndSet(1, 6,  
                    stamp, stamp + 1));  
  
  
            System.out.println("b2=>" + atomicStampedReference.getStamp());  
        },"b").start();  
    }  
}

注意:

Integer 使用了对象缓存机制,默认范围是 -128 ~ 127 ,推荐使用静态工厂方法 valueOf 获取对象实例,而不是 new,因为 valueOf 使用缓存,而 new 一定会创建新的对象分配新的内存空间;