【Java并发编程】synchronized(五):锁膨胀原理分析(JDK6后) 您所在的位置:网站首页 重量级锁原理 【Java并发编程】synchronized(五):锁膨胀原理分析(JDK6后)

【Java并发编程】synchronized(五):锁膨胀原理分析(JDK6后)

2023-09-04 21:38| 来源: 网络整理| 查看: 265

JDK6 为了减少获得锁和释放锁带来的性能消耗,引入了 “偏向锁” 和 “轻量级锁”:锁一共有 4 种状态,级别从低到高依次是:无锁状态、偏向锁状态、轻量级锁状态和重量级锁状态。锁可以升级但不能降级。

在对象头的 Mark Word 中保存了不同的锁状态:

在这里插入图片描述

偏向锁:加锁信息。通过修改 ThreadId 来实现加锁轻量级锁:指针,指向拿锁线程的 Lock Record(里面保存了对象的 MarkWord)。通过修改指针来实现加锁重量级锁:指针,指向对象的 Monitor 对象。通过修改 ObjectMonitor 的 count(++)来实现加锁 1.偏向锁 特点:无竞争(只有一个线程、多个线程但不同时执行)原理:CAS注:偏向锁在 Java 6 和 Java 7 里是默认启用的。由于偏向锁是为了在只有一个线程执行同步块时提高性能,如果你确定应用程序里所有的锁通常情况下处于竞争状态,可以通过JVM参数关闭偏向锁:-XX:-UseBiasedLocking=false,那么程序默认会进入轻量级锁状态。 1.1 获取锁过程

1)访问 Mark Word 中偏向锁的标识是否设置成1,锁标志位是否为 01——确认为可偏向状态。

2)如果为可偏向状态,则测试线程 ID 是否指向当前线程

如果是,进入步骤(5)否则进入步骤(3)

3)如果线程ID并未指向当前线程,则通过CAS操作竞争锁。

如果竞争成功,则将 Mark Word中 线程 ID 设置为当前线程ID,然后执行(5)如果竞争失败,执行(4)

4)如果CAS获取偏向锁失败,则表示有竞争(CAS 获取偏向锁失败说明至少有过其他线程曾经获得过偏向锁,因为线程不会主动去释放偏向锁)。当到达全局安全点(safepoint)时,会首先暂停拥有偏向锁的线程,然后检查持有偏向锁的线程是否活着

PS:因为可能持有偏向锁的线程已经执行完毕,但是该线程并不会主动去释放偏向锁

如果线程不处于活动状态,则将对象头设置成无锁状态(标志位为“01”),然后重新偏向新的线程;如果线程仍然活着,撤销偏向锁后升级到轻量级锁状态(标志位为“00”),此时轻量级锁由原持有偏向锁的线程持有,继续执行其同步代码,而正在竞争的线程会进入自旋等待获得该轻量级锁。

5)执行同步代码。

1.2 释放锁过程:

如上步骤(4)。偏向锁使用了一种等到竞争出现才释放偏向锁的机制:偏向锁只有遇到其他线程尝试竞争偏向锁时,持有偏向锁的线程才会释放锁,线程不会主动去释放偏向锁。

偏向锁的撤销,需要等待全局安全点(在这个时间点上没有字节码正在执行),它会首先暂停拥有偏向锁的线程,判断锁对象是否处于被锁定状态,撤销偏向锁后恢复到未锁定(标志位为“01”)或轻量级锁(标志位为“00”)的状态。

2.轻量级锁 特点:轻量并发(线程少,任务执行快(当任务


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有