Java Synchronize底层原理总结

 更新时间:2023年06月14日 08:43:24   作者:EzreaLwj  
这篇文章主要给大家总结了Java Synchronize底层原理,文中的图文讲解介绍的非常详细,对我们学习Java Synchronize有一定的帮助,需要的朋友可以参考下

对象内存结构

对象头MarkWord 存储对象头的信息,Klass Word 描述对象实例的具体类型

实例数据:成员变量

对齐填充:如果对象头 + 实例变量 不是 8 的整数倍,则通过对齐填充补齐

MarkWord 解析

  • hashcode:25位的对象标识Hash码
  • age:对象分代年龄占4位
  • biased_lock:偏向锁标识,占1位,0表示没有开始偏向锁,1表示开启了偏向锁
  • thread:持有偏向锁的线程ID,占23位
  • epoch:偏向时间戳,占2位
  • ptr_to_lock_record:轻量级锁状态下,指向栈中锁记录的指针,占30位
  • ptr_to_heavyweight_monitor:重量级锁状态下,指向对象监视器Monitor的指针,占30位

LockRecord 锁记录

Markword:记录锁记录的地址

对象引用:引用被加上锁了的对象

重量级锁

Monitor

Monitor 监视器,是由 jvm 提供的,由 C++ 实现的,有三个实现部分

WaitSet:调用了 wait 方法的线程在这里等待,处于 WAITED 状态

EntryList:没有抢到对象锁的线程在这里等待,处于 BLOCKED 状态

Owner:存储已经抢到锁的线程对象

Monitor 的实现属于重量级锁,涉及到 内核态和用户态的切换线程的上下文切换,每个 Java 对象都会关联一个 Monitor 对象,如果使用 Synchronize 给该对象加锁,那么 Java 对象上面的 MarkWord 地址就被设置为指向该 Monitor 对象的指针

轻量级锁

加锁流程

  • 在线程栈中创建一个 Lock Record 对象,它的 object reference 字段指向锁对象
  • 通过 CAS 指令把 Lock Record 的地址存放到对象头的 Markword 中,如果是无锁状态则修改成功,代表该线程获取了轻量级锁
  • 如果当前线程已经持有该锁,就代表是一次锁重入,设置 Lock Record 的第一部分为 null,起到一个重入计数器的作用
  • 如果 CAS 修改失败,则说明发生了竞争,需要膨胀为重量级锁

解锁过程

  • 遍历线程栈,找到所有 object reference 字段等于当前锁对象的 Lock record
  • 如果 Lock recordMarkWordnull,代表这是一次重入,将 obj 设置为 nullcontinue 即可
  • 如果 Lock recordMarkword 不为 null,则利用 CAS 指令将对象头的 markword 与对象对象头的 markword 进行替换,如果成功则恢复无锁状态,如果失败膨胀重量级锁

Markword 记录

开始时的状态

替换后的状态

偏向锁

背景:轻量级锁在没有竞争的时候,每次重入都需要进行 CAS 操作

Java 6 中 引入偏向锁来做进一步的优化:只有第一次 操才使用 CAS 将线程 ID 设置到对象的 markword 头,之后发现这个线程 ID 是自己就不会产生竞争,不用重新 CAS,以后只要不发生竞争,这个对象就归这个线程所有

代码示例:

public class Thread5 {
    private static final Object object = new Object();
    public static void method1() {
        synchronized (object) {
            method2();
        }
    }
    public static void method2() {
        synchronized (object) {
            method3();
        }
    }
    public static void method3() {
        synchronized (object) {
        }
    }
}

总结

Java 中的 Synchronize 有偏向锁、轻量级锁、重量级锁三种形式,分别对应了锁只被一个线程持有、不同线程交替持有锁、多线程竞争的情况

重量级锁:底层使用 Monitor 实现,里面涉及到了用户态和内核态的转换、进程的上下文切换,成本较高,性能比较低

轻量级锁:线程加锁时间是错开的(也就是没有竞争),可以用轻量级锁来优化,轻量级修改了对象头的锁标志,相对重量级锁性能提升了许多,每次修改都是 CAS 操作,保证原子性

偏向锁:一段很长的时间内都只被一个线程使用锁,可以使用偏向锁,第一次获得锁时,会有一个 CAS 操作,之后该线程再获取锁,只需要判断 mark word 中是否是自己的线程 id 即可,而不是开销相对较大的 CAS 命令

以上就是Java Synchronize底层原理总结的详细内容,更多关于Java Synchronize底层原理的资料请关注脚本之家其它相关文章!

相关文章

  • spring cloud内容汇总(各个功能模块、启动、部署)的详细过程

    spring cloud内容汇总(各个功能模块、启动、部署)的详细过程

    Spring Cloud 是一套基于 Spring Boot 的框架集合,用于构建分布式微服务架构,文章介绍了Spring Cloud框架及其相关工具的使用,还详细介绍了如何配置和使用这些功能,包括配置文件、依赖管理以及实际应用示例,感兴趣的朋友一起看看吧
    2024-11-11
  • springboot项目中常用的工具类和api详解

    springboot项目中常用的工具类和api详解

    在Spring Boot项目中,开发者通常会依赖一些工具类和API来简化开发、提高效率,以下是一些常用的工具类及其典型应用场景,涵盖 Spring 原生工具、第三方库(如Hutool、Guava) 和 Java 自带工具,本文给大家介绍springboot项目中常用的工具类和api,感兴趣的朋友一起看看吧
    2025-04-04
  • Java中stream流处理实现数据分组合并

    Java中stream流处理实现数据分组合并

    本文主要介绍了Java中stream流处理实现数据分组合并,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-03-03
  • SpringMVC请求参数别名设置方式

    SpringMVC请求参数别名设置方式

    文章介绍了SpringMVC中请求参数的别名设置方法,通常,接收参数时要求参数名一致,通过@RequestParam注解的value属性,可以为参数设置别名,实现参数名不一致时的准确接收
    2025-10-10
  • Mybatis如何实现InsertOrUpdate功能

    Mybatis如何实现InsertOrUpdate功能

    这篇文章主要介绍了Mybatis如何实现InsertOrUpdate功能,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-05-05
  • Java实现插入排序,希尔排序和归并排序

    Java实现插入排序,希尔排序和归并排序

    这篇文章主要为大家详细介绍了插入排序,希尔排序和归并排序的多种语言的实现(JavaScript、Python、Go语言、Java),感兴趣的小伙伴可以了解一下
    2022-12-12
  • Java并发编程之ConcurrentLinkedQueue源码详解

    Java并发编程之ConcurrentLinkedQueue源码详解

    今天带小伙伴们学习一下Java并发编程之Java ConcurrentLinkedQueue源码,本篇文章详细分析了ConcurrentLinkedQueue源码,有代码示例,对正在学习java的小伙伴们很有帮助哟,需要的朋友可以参考下
    2021-05-05
  • Java HashMap底层原理的全方位深度解析

    Java HashMap底层原理的全方位深度解析

    Java中的HashMap是我们在开发中经常使用的集合之一,它提供了基于哈希表的数据存储方式,使得对数据的插入、删除和查找操作都具有较高的效率,这篇文章主要介绍了Java HashMap底层原理的全方位深度解析,需要的朋友可以参考下
    2026-02-02
  • Springboot注解@Value读取配置文件参数详解

    Springboot注解@Value读取配置文件参数详解

    Spring Boot提供了灵活的配置文件读取机制,主要有两种方式,第一种是使用@Value注解直接在类属性上读取application.yml文件中的配置,这种方式简单直接,但需要为每个配置项单独设置属性,第二种方式是通过@PropertySource注解读取自定义的Properties文件
    2024-11-11
  • springboot的logging.group日志分组方法源码流程解析

    springboot的logging.group日志分组方法源码流程解析

    这篇文章主要为大家介绍了springboot的logging.group日志分组方法源码流程解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12

最新评论