CAS理解

概述

  1. CAS是多线程的一个基础,可以先了解一下CAS
  2. CAS引入的条件就是:在不加锁的情况下,实现多线程对同一个数据的修改是线程安全的
  3. 可以简单理解成不加synchronized却可以实现线程安全
  4. 有点像乐观锁

    代码示例

    image.png

    图解

    多线程教程 - 图2

    ABA问题

    比较E和N的时候,E改了2次,又改回之前的值了
    解决方案:除了比较值,再加一个字段,然后同时比较这个值和新加的这个字段

  5. 增加加版本号,每次改的时候版本+1

  6. 增加boolean字段判断,类java.util.concurrent.atomic.AtomicStampedReference

    CAS本质实现

    同synchronize和volite的实现是一样的
    JVM的实现我们就采用HostSpot(官方的)
    image.png

    JOL(java object layout)来理解CAS

    image.png
    image.png
    如果关闭了类型指针压缩,markword 8个 class pointer8个 instance data0个 对齐0个—->总共16个字节
    image.png
    一个自定义对象在堆里面占据了几个字节呢?
    image.png
    加锁以后的信息存放在哪里呢?
    image.png
    jdk1.8 锁的升级过程(也可以看做对象的markword里记录了啥呢?)

  7. 刚new出来的对象

  8. 偏向锁
  9. 轻量级锁(无锁,自旋锁)
  10. 重量级锁

多线程教程 - 图9
锁升级的图解
image.png
老师总结
image.png
锁降级
只有GC的时候会发生,一般可以认为没有意义,简单认为锁降级不存在
锁消除
image.png
这个StringBuffer对象是线程安全的,里面的操作用synchronize修饰的,但是这个方法存在于一个方法里面,是局部变量(栈私有),不涉及线程安全问题,怎么分析线程安全呢?通过分析这个对象是否跑出了这个方法(并非逃逸分析),因此jvm会帮我们自动消除StringBuffer对象内部的锁,提升效率

锁粗化
image.png
jvm会把append方法内的锁,放到while外面,本来要加锁解锁100次,现在只要1次