1. JMM


    image.png

    • 可见性:就是某个线程对主内存内容的更改,应该立刻通知到其它线程
    • 原子性:指一个操作是不可分割的,不能执行到一半,就不执行了
    • 有序性:就是指令是有序的,不会被重排
    1. volatile关键字
    • 描述:volatile关键字是Java提供的一种轻量级同步机制。它能够保证可见性有序性,但是不能保证原子性
    • 例子
      • 单例模式的安全问题
    1. CAS
    • 描述:CAS是指Compare And Swap比较并交换,底层调用了Unsafe.getAndAddInt()方法,Unsafe类的大部分方法都是native的。

      1. public final int getAnddAddInt(Object var1,long var2,int var4){
      2. int var5;
      3. do{
      4. var5 = this.getIntVolatile(var1, var2);
      5. } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
      6. return var5;
      7. }
    • 原理:这个方法的var1和var2,就是根据对象偏移量得到在主内存的快照值var5。然后compareAndSwapInt方法通过var1和var2得到当前主内存的实际值。如果这个实际值快照值相等,那么就更新主内存的值为var5+var4。如果不等,那么就一直循环,一直获取快照,一直对比,直到实际值和快照值相等为止。

    • 缺点

      • 一直循环,CPU开销比较大
      • 只能保证一个变量的原子操作,多个变量依然要加锁
      • 引出了ABA问题
    • 相关问题

      • ABA问题:比较并交换的循环,存在一个时间差,线程T1将值从A改为B,然后又从B改为A。线程T2看到的就是A,但是却不知道这个A发生了更改如果只注重头和尾就不影响。
        • 解决办法:加版本号,例如AtomicStampedReference就是通过加版本号ABA问题的解决的。