详解Java对象结构与对象锁的升级

详解Java对象结构与对象锁的升级

Java对象结构

Java对象在内存中的实际存储由三部分组成:对象头、实例数据和对齐填充。

对象头

对象头是Java对象的一部分,用于存储对象自己的运行时数据,包括以下内容:

  • Mark Word: 用来锁定对象、记录对象哈希值、记录对象所属的分代年龄等信息。
  • Class: 指向对象的Class对象。

在Java 8中,对象头的大小为12字节。

实例数据

实例数据存储对象的实例变量,实例数据相对于对象头的大小是不定的,因为它取决于对象的实例变量数量和类型。

对齐填充

为了对齐对象在内存中的地址,可能需要在实例数据末尾补充填充数据,使得对象的大小是8字节的整数倍。在Java 8中,所需的填充量最多为7个字节。

对象锁的升级

Java中的对象锁分为偏向锁、轻量级锁和重量级锁。

偏向锁

偏向锁是一种针对加锁频繁性不高的场景的优化,偏向锁的意思是,偏向某个线程,这个线程在获取锁之后,当再次进入同步块时,因为上一次已经获取过锁了,所以可以直接获得锁,而不需要重新去竞争。

下面是一个偏向锁示例:

public class BiasedLockDemo {
    private static final int COUNT = 10_000_000;
    public static void main(String[] args) throws InterruptedException {
        Object obj = new Object();
        long start = System.currentTimeMillis();
        for (int i = 0; i < COUNT; i++) {
            synchronized (obj) {
                // do nothing
            }
        }
        System.out.println("Synchronized cost : " + (System.currentTimeMillis() - start) + "ms");

        Thread.sleep(10000);

        start = System.currentTimeMillis();
        for (int i = 0; i < COUNT; i++) {
            synchronized (obj) {
                // do nothing
            }
        }
        System.out.println("Synchronized cost : " + (System.currentTimeMillis() - start) + "ms");
    }
}

在上面的示例中,第一次进入同步块时,JVM会偏向此线程,并记录对象的Mark Word为偏向锁模式。因为只有一个线程,所以不会有竞争,性能最优。第二次进入同步块时,因为对象已经记录了偏向线程,所以直接判断Mark Word是否指向该线程,如果是,则直接获取锁,不再竞争锁。

轻量级锁

如果一个线程没有成功获取偏向锁,或者偏向锁被取消了,那么它就会尝试轻量级锁来获取锁。轻量级锁使用CAS操作,将对象头中的Mark Word复制到线程的栈帧中,表示当前线程已经获得了这个锁。如果CAS操作成功,则当前线程成功获得锁,继续执行同步块。如果CAS操作失败,表示有竞争,此时当前线程会自旋一段时间,等待其他线程释放锁。

下面是一个轻量级锁示例:

public class LightweightLockDemo {
    private static final int COUNT = 10_000_000;
    public static void main(String[] args) throws InterruptedException {
        Object obj = new Object();
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < COUNT; i++) {
                synchronized (obj) {
                    // do nothing
                }
            }
        }, "thread-1");
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < COUNT; i++) {
                synchronized (obj) {
                    // do nothing
                }
            }
        }, "thread-2");

        long start = System.currentTimeMillis();
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println("Synchronized cost : " + (System.currentTimeMillis() - start) + "ms");
    }
}

在上面的示例中,两个线程同时竞争同一个对象锁,因此会导致竞争,此时第二个线程会自旋等待第一个线程释放锁。

重量级锁

如果轻量级锁获取失败,则会进入重量级锁模式。此时线程会进入操作系统的内核态,进入阻塞状态,等待其他线程释放锁。

下面是一个重量级锁示例:

public class HeavyweightLockDemo {
    private static final int COUNT = 10_000_000;
    public static void main(String[] args) {
        Object obj = new Object();
        synchronized (obj) {
            try {
                Thread.sleep(100000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在上面的示例中,线程进入同步块后,会一直等待100秒,此时其他线程无法获取锁,只能等待该线程释放锁,因此此时已经进入重量级锁模式。

总结

Java对象在内存中的实际存储由三部分组成:对象头、实例数据和对齐填充。对象锁分为偏向锁、轻量级锁和重量级锁。在多线程并发环境下,不同的锁模式可以优化性能,提升程序的吞吐量。

以上就是Java对象结构与对象锁升级的详细攻略,希望能够对你有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解Java对象结构与对象锁的升级 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • JVM工作原理和工作流程简述

    JVM工作原理和工作流程简述 JVM是Java虚拟机的缩写,是一种Java应用程序的运行环境。JVM的主要作用是将编写好的Java程序分解成字节码文件,然后在JVM中解释执行这些字节码,最终将结果输出。JVM具有跨平台、可移植、安全、动态性等优点,广泛应用于计算机领域。下面将对JVM工作原理和工作流程进行简述。 JVM工作原理 JVM的工作原理主要包括以下几…

    Java 2023年5月26日
    00
  • spring+mybatis实现图书管理系统

    以下是“spring+mybatis实现图书管理系统”的完整攻略。 1. 环境准备 首先需要准备好开发环境,包括以下工具和框架: JDK(Java Development Kit): 用于编译和运行Java程序的开发工具包。 Eclipse(或其他Java开发工具):用于编写和调试Java代码的集成开发环境(IDE)。 Maven:Java项目的构建工具,用…

    Java 2023年6月15日
    00
  • JSP技术简介

    JSP技术是运用Java语言的Web编程技术之一,以便于开发人员动态地生成HTML、XML或其他类型的Web页面。在JSP页面中,可以将静态内容、JSP标记和Java代码混合在一起来生成动态Web页面。 JSP页面结构 JSP页面以.jsp后缀作为文件后缀名。在JSP页面中,可以包含以下几种元素: 指令:指示服务器或容器如何翻译JSP页面,并且在整个页面中只…

    Java 2023年6月15日
    00
  • Java 中EasyExcel的使用方式

    Java 中EasyExcel的使用方式 什么是EasyExcel EasyExcel 是阿里巴巴开源的一个 Java 操作 Excel 的简单工具,具有自动识别 Excel 文件的类型(2003/2007/2010等)及生成 Excel 文件,读取数据和流式写入数据的功能。为我们处理 Excel 带来了很大的便利性。 EasyExcel 的使用方式 1. …

    Java 2023年5月19日
    00
  • java开发BeanUtils类解决实体对象间赋值

    Java开发中,BeanUtils类是一个常用的工具类,用于解决Java实体对象间的属性赋值问题。在实际开发中,我们通常需要根据一个实体对象的属性值赋值到另一个实体对象的属性中,BeanUtils类就可以快速实现这个过程。 下面是使用BeanUtils类解决实体对象间属性赋值的完整攻略: 1. 引入依赖 在项目中引入BeanUtils类需要先在pom文件中添…

    Java 2023年5月26日
    00
  • hibernate查询缓存详细分析

    Hibernate查询缓存详细分析 Hibernate是一个开源的持久性框架,支持使用注解、XML文件或者API访问数据库。Hibernate查询缓存可以显著提高应用程序的执行效率和性能。本文将分析Hibernate查询缓存并提供一些示例说明。 什么是Hibernate查询缓存 Hibernate查询缓存是指在缓存中缓存查询结果,避免重复执行相同的SQL语句…

    Java 2023年5月20日
    00
  • PHP-Java-Bridge使用笔记

    PHP-Java-Bridge使用笔记 什么是PHP-Java-Bridge? PHP-Java-Bridge是一个连接PHP和Java的桥梁,提供了一种方法来使用PHP脚本访问Java类库和执行Java代码。它支持通过Java应用程序服务器从PHP访问Java组件。 安装PHP-Java-Bridge 下载PHP-Java-Bridge 可以从官网 htt…

    Java 2023年5月26日
    00
  • 什么是栈区?

    以下是关于栈区的详细讲解和使用攻略: 栈区的作用是什么? 栈区(Stack)是一种用于存储方法调用和局部变量的内区域。栈区是线程有的,其大小可以通过 -Xss 参数进行设置。 栈区的使用攻略 使用栈区,需要注意以下点: 在程序发中需要合理使用内存,避免出现栈溢出等问题。 在方法调用过程中,需要注意方法的嵌套深度避免出现栈溢出等问题。 在方法中定义局部变量时,…

    Java 2023年5月12日
    00
合作推广
合作推广
分享本页
返回顶部