锁升级的过程

文章目录

  • 一. 问题背景
  • 二. 锁升级的过程

一. 问题背景

面试的过程中可能会问到“锁升级的过程”。

二. 锁升级的过程

  • 锁的状态有无锁、偏向锁、轻量级锁、重量级锁。锁的状态会随着锁的竞争升级,这是一个不可逆的过程。

  • 代码进入同步块的时候,首先在栈帧中创建一个锁记录(Lock Record),锁记录是一个数据结构。锁对象的Mark Word会被复制到锁记录中,此时锁记录中称为Displaced Mark Word。

  • 一开始是无锁状态,对象锁的对象头Mark Word中的锁标记是01,是否偏向锁的位置上是0。当锁对象第一次被线程获取的时候,锁对象的Mark Word中的是否偏向锁的位置上变为1,锁标记仍为01。通过使用CAS操作将当前线程的线程ID设置到锁对象的Mark Word中,如果设置成功了,那么当前线程得到了这个锁对象了,可以执行同步代码块的代码,以后每次进入这个锁相关的同步块时,都可以不再使用任何操作(比如lock,cas之类),此时处于偏向锁状态。当有另一个线程尝试获取偏向锁时,偏向模式宣告结束。根据锁对象目前是否处于锁定状态,撤销偏向后恢复到未锁定状态或者轻量级锁定的状态。

  • 当有一条线程尝试获取处于轻量级锁的锁对象时,首先在栈帧中创建锁记录,然后将锁对象的Mark Word复制到锁记录中,然后使用CAS操作(一般是10次)把锁对象的Mark Word设置为指向锁记录的指针,如果设置成功(后面的自旋次数相应提高,这就是适应性自旋),那么这个线程就拥有该对象的锁,并且对象的Mark Word的锁标志位变为了00。如果设置失败,那么首先检查对象的Mark Word是否指向当前线程的栈帧,如果是则说明当前线程已经拥有这个对象的锁,可以直接进入同步块执行,否则说明则这个锁对象已经被其他线程占用了。那么轻量级锁膨胀为重量级锁。锁对象的Mark Word中锁标志变为10,Mark Word指向重量级锁,后面等待锁的线程也进入阻塞状态。

  • 轻量级锁的解锁过程通过CAS操作进行。如果锁对象的Mark Word仍指向线程的锁记录,那么通过CAS操作把对象的Mark Word与线程中复制得来的Displaced Mark Word替换回来。如果替换成功,那么解锁成功;否则在释放锁的同时,要唤醒阻塞的线程。

你可能感兴趣的:(Java面试题笔记)