详解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日

相关文章

  • Java8中方法引用的使用详解

    Java8中方法引用的使用详解 什么是方法引用? Java8中的方法引用是一种新特性,使用方法引用可以更加简洁的定义Lambda表达式。方法引用是指引用已经存在的方法而不是声明一个Lambda表达式来调用该方法。 方法引用的语法 方法引用的语法在箭头函数的基础上添加一个双冒号“::”,语法格式如下: object::instanceMethod ClassN…

    Java 2023年5月26日
    00
  • Java基础之Thymeleaf的简单使用

    下面是“Java基础之Thymeleaf的简单使用”的完整攻略。 1. 什么是Thymeleaf Thymeleaf是一种服务器端Java模板引擎,它能够处理HTML、XML、JavaScript、CSS、文本等模板。与其他模板引擎相比,Thymeleaf有以下特点: 语法简单且易于学习; 支持自然模板:模板可以在浏览器中预览,而不需要部署到客户端; 支持表…

    Java 2023年5月23日
    00
  • AngualrJS中每次$http请求时的一个遮罩层Directive

    为了在 AngularJS 发送 $http 请求时展示进度条或遮罩层效果,我们可以创建自定义 Directive。下面是一个实现 $http 遮罩层的完整攻略: 第一步:创建遮罩层 Directive 我们可以创建一个自定义的 Directive,把遮罩层模板添加到页面中。在请求使用 $http 发送请求前,遮罩层应该是不可见的,当请求被发出时,遮罩层应该…

    Java 2023年6月15日
    00
  • 做Java开发如何月薪达到两万,需要什么技术水平

    如何成为月薪达到两万的Java开发攻略 作为Java开发工程师,月薪达到两万并不是难事。关键在于具备足够的技术水平和项目经验。下面是我们总结的攻略。 技能和技术水平 1. 扎实的Java基础 Java开发基础是成为优秀Java开发人员的重要基础。在掌握掌握Java基础语法、多线程、集合框架、IO/NIO、反射、注解、Lambda、Stream等知识的基础上,…

    Java 2023年5月26日
    00
  • Spring Security如何实现升级密码加密方式详解

    Spring Security如何实现升级密码加密方式详解 Spring Security是一个强大且灵活的身份验证框架,可以应用于任何Java应用程序中。它允许您轻松地添加身份验证和授权功能到应用程序中,并且提供了强大的加密和解密功能。本文将详细讲解如何使用Spring Security升级密码加密方式。 什么是密码加密和升级密码加密方式? 密码加密是指将…

    Java 2023年6月3日
    00
  • Java 栈与队列超详细分析讲解

    《Java 栈与队列超详细分析讲解》是一篇介绍Java中栈与队列数据结构的文章,以下为该文章的详细攻略: 一、栈的介绍 1.1 栈的定义 栈是一种后进先出(LIFO)的数据结构。栈只允许在栈顶进行插入和删除操作,因此它是一个不可复用的数据结构。 1.2 栈的应用 栈在计算机科学中有广泛的应用,包括函数调用、表达式求解、内存管理等方面。 1.3 Java中栈的…

    Java 2023年5月26日
    00
  • Java 异常java.lang.NoSuchFieldException解决方案

    首先让我们了解一下Java中的异常。 Java中的异常指的是程序在执行过程中遇到的错误或者异常状况,由于这些错误或异常状况的出现不可避免,因此对于Java程序员而言,处理异常是必不可少的一项技能。 其中,java.lang.NoSuchFieldException是一种我们常见的异常类型。这个异常意味着在运行时,Java虚拟机无法找到特定的类或接口中所声明的…

    Java 2023年5月27日
    00
  • Java Web 简单的分页显示实例代码

    下面是详细讲解“Java Web 简单的分页显示实例代码”的完整攻略,包括两条示例说明: 1. 分页显示实现原理 在实现分页显示之前,我们需要先了解分页的原理。当我们在页面中点击“下一页”或者“上一页”等翻页按钮时,客户端会向服务器发送请求,请求需要显示的数据的页数及每页显示的数据数量。服务器收到请求后,根据请求参数查询指定页数的数据,返回给客户端,客户端再…

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