偏向锁

113 阅读2分钟

「这是我参与2022首次更文挑战的第18天,活动详情查看:2022首次更文挑战」。

锁的升级和对比

在JDK1.6中引进了偏向锁和轻量级锁。使用锁一共有4种形态,随着锁的竞争情况逐渐升级。且锁的升级不可逆,只能升级,不能降级。这是为了提高获得锁和释放锁的效率

无锁状态 -> 偏向锁状态 -> 轻量级锁状态 -> 重量级锁状态

偏向锁

HotSport作者发现,锁在大多情况下多为一个线程获得,不存在多线程竞争,所以基于这样的情况下,原来的锁的获得就略显复杂。为了解决这一问题引入了偏向锁来降低获得锁的代价

具体的操作流程为:

  1. 会在栈帧和对象头的锁记录里存放偏向线程的ID,然后该线程在进入和退出同步块时不需要使用CAS操作来进行加锁或者解锁。
  2. 在加锁或者解锁时需要检测偏向锁是否储存当前线程的ID,如果没有则再检测MarkWord里是否为偏向锁的标识是否为1,如果不为1则使用CAS去竞争锁,如果为1则去尝试使用CAS把对象头的偏向锁指向当前线程。

偏向锁的撤销

偏向锁采取的政策为等到竞争出现才释放锁的机制,所以当其他线程去竞争锁时,拥有偏向锁的线程才会释放锁。

  1. 要等到全局安全点(没有正在执行的字节码)。
  2. 然后暂停拥有偏向锁的线程。
  3. 检测持有偏向锁的线程是否存活。
  4. 如果不处于活动状态则将对象头设置为无锁模式。
  5. 如果依旧存活,拥有偏向锁的栈会被执行,遍历偏向对象的锁记录,要么把栈中的锁记录和对象头的Mark Word要么重新偏向于其他线程,要么恢复到无锁状态或者标记对象不适合作为偏向锁。

关闭偏向锁

偏向锁在java6和java7里是默认启用的,但是它存在程序启动后的几秒延迟,可以使用JVM参数来关闭偏向锁,然后程序就会进入轻量级锁状态。