synchronized锁升级过程

synchronized的介绍
  synchronized可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时它还可以保证共享变量的内存可见性,synchronized用的锁存在Java对象头里,Java对象头里的Mark Word默认存储对象的HashCode、分代年龄和锁标记位。在运行期间,Mark Word里存储的数据会随着锁标志位的变化而变化。64位JVM的Mark Word可能变化存储为以下5种数据:
synchronized锁升级过程
锁的状态
  优先级从低到高,无锁状态–>偏向锁状态–>轻量级锁状态–>重量级锁状态,锁只能升级不能降级。
  无锁状态:
  偏向锁状态:当一个线程访问同步块对象时,会获取这个对象的对象锁。如果该对象的对象头锁状态是无锁状态,则通过cas去获取锁,并在对象头中记录该线程的线程id。如果是偏向锁状态,并且对象头中的线程id和当前线程id不一致,那么会判断对象头中记录的线程是否存活,如果没有,则将锁对象重置为无锁状态,其他线程可以竞争将其设置为偏向锁。如果存活,那么会立即查找该线程的栈帧信息,如果该线程仍需要继续持有锁,暂停线程,撤销偏向锁,升级为轻量级锁,如果不需要,则将锁对象重置为无锁状态,其他线程可以竞争将其设置为偏向锁。
  轻量级锁状态:
    轻量级锁加锁:线程在执行同步块之前,JVM会将对象头中的Mark Word复制到栈帧锁记录中,官方称为Displaced Mark Word。然后线程尝试使用CAS将对象头中的Mark Word替换为指向栈帧锁记录的指针。如果成功,当前线程获得锁,如果失败,表示其他线程竞争锁,当前线程便尝试使用自旋来获取锁,当自旋次数达到一定次数时,锁会升级为重量级锁。
    轻量级锁解锁:轻量级解锁时,会使用原子的CAS操作将Displaced Mark Word替换回到对象头,如果成功,则表示没有竞争发生。如果失败,表示当前锁存在竞争,锁就会膨胀成重量级锁。
  重量级锁状态:是让争抢锁的线程从用户态转换成内核态。让cpu借助操作系统进行线程协调。
synchronized锁升级过程