了解Java中的自旋锁, 轻量锁, 重量锁(看不懂找我)

时间:2024-03-28 22:25:16

闲来整理下, 都是自己理解的东西, 可能不是全然正确, 和大家一起探讨.

了解sychronize锁定了什么

了解这三种锁, 先要从synchronize关键字说起.sychronize其实最终锁定的是对象. 不过 synchronize 加在 方法上, 代码块上, 静态代码块上. 加在这三个地方, 锁定的对象是不一样的.

synchronize修饰 锁定对象
方法 锁定的是调用者对象
代码块 synchronize(被锁定对象){}
静态代码块 当前class对象

了解对象的 Mark word(对象头)

当线程调用到synchronize 修饰的代码时, 会去修改被锁定对象的 Mark word (对象头)中一些属性, 我们看下对象头有哪些属性.

了解Java中的自旋锁, 轻量锁, 重量锁(看不懂找我)
可以看到在对象头中, 关于无锁, 偏向, 轻量, 重量锁的属性是不一样的.

实际出现锁的时机与锁升级

我们现在假设三种情况:

  1. 只有T1 线程调用sychronize 代码 (出现偏向锁):
    step1 : 首先通过 被锁定对象 的对象头属性, 判断是否是偏向锁.
    case1 如果是偏向锁 : 比较ThreadId是否相同,相同则执行.
    case2 如果不是偏向锁 : , 通过cas 修改ThreadId, 将线程的threadId 设置进去.
    这个时候只有偏向锁. 每次T1 线程调用的时候, 只需要判断是否偏向锁, 对比ThreadId 就可以了.

  2. T1, T2 两个线程调用sychronize 代码( 出现偏向锁 升级为轻量锁)
    假设T1 获取到执行权, T2 线程与T1 线程出现竞争. 将轻量锁属性设置1. T2 线程没有获取到执行权, 就开始自旋等待(自旋一定次数,jvm参数可配置) . 自旋的开销, 比映射到内核切换线程的开销要低.

  3. T1, T2 两个线程调用sychronize 代码(出现 轻量锁 升级为重量锁)
    第二种情况, 提到了自旋一定次数. 那么如果超过指定次数. 轻量锁就会升级成为重量锁. 重量锁就是利用Monitor 指针. 通过系统来分配切换代码的执行权.

    总结:

    这些是自己总结的一些内容. 欢迎指正探讨.
    了解Java中的自旋锁, 轻量锁, 重量锁(看不懂找我)