高薪程序员必修课-JVM创建对象时如何解决多线程内存抢占问题

news2024/11/13 9:13:38

前言

        在JVM中,堆的内存分配过程涉及到线程安全性的保障,具体来说涉及到对象的内存分配时,并不是简单的抢占式分配,而是通过一些机制来保证线程安全和高效的内存管理。下面解释一下JVM是如何设计来保证线程安全的:

内存分配的线程安全性保障

  1. 线程私有分配缓冲区(Thread Local Allocation Buffer, TLAB)

    JVM在Java堆中为每个线程分配了一个私有的内存分配缓冲区(TLAB),用于对象的快速分配。TLAB的作用包括:

    • 减少线程之间的竞争:每个线程都有自己的TLAB,避免了多线程之间的竞争,提高了分配效率。
    • 延迟同步:线程在TLAB中分配对象时,不需要加锁,只有当TLAB空间不足时才需要进行同步操作。
  2. 线程安全的内存分配指针

    JVM为每个线程维护了一个线程本地的内存分配指针(Allocation Pointer),用于标记下一个可以分配对象的位置。每次分配对象时,线程会使用这个指针来确定在TLAB中的分配位置,从而保证了线程安全性。

对象的初始化和安全发布

在Java中,对象的初始化和安全发布也是保证线程安全的关键点:

  • 构造方法:JVM保证了在对象的构造方法执行完毕之前,对象的引用不会被其他线程可见。这是通过内存屏障(Memory Barrier)和特定的指令顺序来实现的。

  • volatile关键字:在多线程环境下,使用volatile关键字修饰的变量可以保证可见性,即一个线程修改了volatile变量的值,其他线程可以立即看到最新的值。

  • final关键字:使用final关键字修饰的变量或对象引用,其初始化过程具有一定的保证,可以避免对象的不安全发布。

内存屏障(Memory Barrier)

JVM在进行内存操作时,会使用内存屏障(Memory Barrier,或称内存栅栏)来保证指令重排序的正确性和可见性。内存屏障包括:

  • 写屏障(Store Barrier):确保在写入操作完成之前,不会将后续的写入操作重排序到写入操作之前。

  • 读屏障(Load Barrier):确保在读取操作完成之后,不会将前面的读取操作重排序到读取操作之后。

这些屏障可以保证线程在执行操作时,能够看到正确的内存状态,从而保证了线程之间操作的可见性和有序性,进而保证了对象的安全发布和线程安全。

示例代码解释

下面是一个简单的示例,展示了对象的初始化和安全发布的过程:

public class SafeInitializationExample {

    // 可见性保证,使用volatile关键字
    private volatile static SafeInitializationExample instance;

    private SafeInitializationExample() {
        // 构造方法
    }

    public static SafeInitializationExample getInstance() {
        // 使用双重检查锁定(Double-Checked Locking)来实现线程安全的单例模式
        if (instance == null) {  // 第一次检查
            synchronized (SafeInitializationExample.class) {
                if (instance == null) {  // 第二次检查
                    instance = new SafeInitializationExample();  // 创建对象
                }
            }
        }
        return instance;
    }

    public static void main(String[] args) {
        // 创建多个线程同时获取单例对象
        Runnable task = () -> {
            SafeInitializationExample obj = SafeInitializationExample.getInstance();
            System.out.println("Instance hash code: " + obj.hashCode());
        };

        // 启动多个线程
        for (int i = 0; i < 5; i++) {
            new Thread(task).start();
        }
    }
}

示例代码说明

  1. volatile关键字:在示例中,instance变量被声明为volatile,这样可以确保多线程环境下,对instance的写操作对其他线程立即可见。这是保证对象安全发布的关键之一。

  2. 双重检查锁定(Double-Checked Locking)getInstance()方法使用双重检查锁定来实现延迟初始化单例对象。这种方式既保证了线程安全,又避免了每次调用都加锁的性能开销。

  3. 对象的初始化:在getInstance()方法中,当instance为null时,通过synchronized关键字确保只有一个线程进入临界区创建对象,避免多线程同时创建多个实例的问题。

  4. 多线程测试:在main方法中,创建多个线程同时调用getInstance()方法获取单例对象,通过打印对象的哈希码可以验证单例对象的唯一性和正确性。

运行结果分析

        当运行示例代码时,你会看到多个线程同时访问getInstance()方法,但只会创建一个SafeInitializationExample的实例对象,并且这个实例对象是唯一的。这样的设计保证了在多线程环境下,对象的安全初始化和安全发布。

总结

        JVM通过使用线程私有的内存分配缓冲区(TLAB)、内存屏障和特定的对象初始化机制,来保证对象的安全创建、初始化和发布。这些机制有效地避免了多线程环境下的竞争条件和数据不一致问题,保证了Java程序在并发情况下的稳定性和正确性。


 ⭐️⭐️ ⭐️ ⭐️ ⭐️ 好书推荐
《Java项目开发全程实录》(第4版)

【内容简介】

        《Java项目开发全程实录(第4版)》以企业QQ、蓝宇快递打印系统、开发计划管理系统、酒店管理系统、图书馆管理系统、学生成绩管理系统、进销存管理系统、神奇Book—图书商城、企业门户网站、棋牌游戏系统之网络五子棋10个实际项目开发程序为案例,从软件工程的角度出发,按照项目的开发顺序,系统、全面地介绍了J2SE和J2EE项目的开发流程。从开发背景、需求分析、系统功能分析、数据库分析、数据库建模、网站开发和网站发布或者程序打包与运行方面进行讲解,每一过程都进行了详细的介绍。

📚 京东购买链接:《Java项目开发全程实录》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1905990.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

输入Rviz打不开,显示could not contact Ros master at[..],retrying

直接输入rviz会报错无法打开 解决方法&#xff1a; 先输入roscore&#xff0c;再用ctrlaltt打开新终端&#xff0c;在新终端输入rviz/rosrun rviz rviz即可

密码技术中分组模式解析

目录 1. 概述 2. ECB模式 2.1 概述 2.2 ECB模式的加密 2.3 ECB模式的解密 2.4 优点 2.5 缺点 3. CBC模式【推荐】 3.1 概述 3.2 CBC模式的加密 3.3 CBC模式的解密 3.4 优点 3.5 缺点 4. CFB模式 4.1 概述 4.2 CFB模式的加密 4.3 CFB模式的解密 4.4 优点 4.…

一二三应用开发平台应用开发示例(6)——代码生成、权限配置、运行效果查看

生成代码 完成配置工作&#xff0c;接下来就是见证奇迹的时刻~ 返回到实体列表&#xff0c;选中“文件夹”记录&#xff0c;点击“生成代码”按钮&#xff0c;提示成功后&#xff0c;在项目的output目录下输出了平台基于配置模板产生的各层代码&#xff0c;在原有后端的基础上…

【国产开源可视化引擎Meta2d.js】网格

画布背景网格 在线体验&#xff1a; 乐吾乐2D可视化 示例&#xff1a; // 设置默认缺省网格属性 meta2d.store.options.grid true; // 开启 meta2d.store.options.gridColor eeeeee; // 网格线条颜色 meta2d.store.options.gridSize 10; // 格子大小// 设置单个图纸的网格…

java ReadWriteLock接口

在 Java 中&#xff0c;ReadWriteLock 接口的实现类ReentrantReadWriteLock 类提供了一种允许多个线程同时读取某一资源但只允许一个线程写的锁定机制。这种机制可以提高并发性能&#xff0c;特别是在读操作远多于写操作的场景下。 特性&#xff1a; 可重入&#xff1b;不存…

管理《欧盟数字服务法》交易者要求

《数字服务法》合规性 根据《数字服务法》(DSA) 的要求&#xff0c;对于在欧盟地区 (EU) 通过 App Store 分发 App 的所有交易商&#xff0c;Apple 需要验证并显示其联系信息。请指明你是否将以交易商或非交易商的身份在欧盟地区分发任何内容。进一步了解你是否应为交易商。 …

图解 RocketMQ 架构

写在前面 Kafka、RocketMQ都是很出名的中间件&#xff0c;上次我们讲解了Kafka&#xff0c;这次我们来讲讲RocketMQ的原理。 基本架构图 解析 RocketMQ 总共可以分成四个模块 NameServer&#xff1a;提供服务发现和路由功能&#xff0c;管理各种元数据信息。Broker&#xf…

Golang | Leetcode Golang题解之第222题完全二叉树的节点个数

题目&#xff1a; 题解&#xff1a; func countNodes(root *TreeNode) int {if root nil {return 0}level : 0for node : root; node.Left ! nil; node node.Left {level}return sort.Search(1<<(level1), func(k int) bool {if k < 1<<level {return false}…

tomcat原理、结构、设计模式

1 what 一种web服务器&#xff0c;运行java servlet、jsp技术&#xff0c;能为java web提供运行环境并通过http协议处理客户端请求。即tomcat http服务器 servlet容器。同类产品有jetty Web应用&#xff1a;Web应用是指通过Web浏览器访问的应用程序&#xff0c;它使用Web技术…

ctfshow-web入门-文件上传(web151-web160)

目录 1、web151 2、web152 3、web153 4、web154 5、web155 6、web156 7、web157 8、web158 9、web159 10、web160 1、web151 试了下前端只能传 png 后缀的 将一句话木马改成 png 后缀&#xff0c;上传后用 burpsuite 抓包 绕过前端检测后&#xff0c;改回 php 后缀&am…

Python28-9 XGBoost算法

XGBoost&#xff08;eXtreme Gradient Boosting&#xff0c;其正确拼写应该是 "Extreme Gradient Boosting"&#xff0c;而XGBoost 的作者在命名时故意使用了不规范的拼写&#xff0c;将“eXtreme”中的“X”大写&#xff0c;以突出其极限性能和效率&#xff09;是一…

【测试】系统压力测试报告模板(Word原件)

系统压力测试&#xff0c;简而言之&#xff0c;是在模拟高负载、高并发的环境下&#xff0c;对系统进行全面测试的过程。它旨在评估系统在面对极端使用条件时的性能表现&#xff0c;包括处理能力、响应时间、资源消耗及稳定性等关键指标。通过压力测试&#xff0c;开发团队能够…

【OJ】运行时错误(Runtime Error)导致递归爆栈问题

在进行OJ赛时&#xff0c; 题目&#xff1a;给你一个整数n&#xff0c;问最多能将其分解为多少质数的和。在第一行输出最多的质数数量k,下一行输出k个整数&#xff0c;为这些质数。 出现运行时错误 代码如下&#xff1a; def main():# code heren int(eval(input()))list …

力扣-双指针1

何为双指针 双指针指向同一数组&#xff0c;然后配合着进行搜索等活动。 滑动窗口的时候很好使用。 167.两数之和Ⅱ-输入有序数组 167. 两数之和 II - 输入有序数组 题目 给你一个下标从 1 开始的整数数组 numbers &#xff0c;该数组已按 非递减顺序排列 &#xff0c;请你从…

2024年 春秋杯 网络安全联赛夏季赛 Web方向 题解WirteUp 部分

brother 题目描述&#xff1a;web哥&#xff0c;打点容易提权难。 打点就是最简单的SSTI。 执行下find / -user root -perm -4000 -print 2>/dev/null找一下具备suid权限的命令 /usr/lib/dbus-1.0/dbus-daemon-launch-helper /usr/bin/chsh /usr/bin/gpasswd /usr/bin/n…

WPF UI InkCanvas 导师演示画板 演示 笔记 画笔 识别

<Grid><InkCanvas Name"inkCanvas"/><Button Content"识别" Click"Button_Click" VerticalAlignment"Bottom"/></Grid> 引用内库 Ink ink new Ink(); private void Button_Click(object sender, RoutedEvent…

逆变器学习笔记(三)

DCDC电源芯片外围器件选型_dcdc的comp补偿-CSDN博客、 1.芯片的COMP引脚通常用于补偿网络&#xff1a; 芯片的COMP引脚通常用于补偿网络&#xff0c;在控制环路中发挥重要作用。COMP引脚接电容和电阻串联接地&#xff0c;主要是为了稳定控制环路、调整环路响应速度和滤波噪声…

LabVIEW机器视觉技术在产品质量检测中有哪些应用实例

LabVIEW的机器视觉技术在产品质量检测中有广泛的应用&#xff0c;通过图像采集、处理和分析&#xff0c;实现对产品缺陷的自动检测、尺寸测量和定位校准&#xff0c;提高生产效率和产品质量。 1. 电子元器件质量检测 在电子制造业中&#xff0c;电子元器件的质量检测是确保产品…

Java版Flink使用指南——自定义无界流生成器

大纲 新建工程自定义无界流 使用打包、提交、运行 在《Java版Flink使用指南——从RabbitMQ中队列中接入消息流》一文中&#xff0c;我们让外部组件RabbitMQ充当了无界流的数据源&#xff0c;使得Flink进行了流式处理。在《Java版Flink使用指南——将消息写入到RabbitMQ的队列中…

AntV X6 图编辑引擎速通

前言&#xff1a;参考 [AntV X6 官网](https://x6.antv.antgroup.com/) 一、简介 X6 可以快速搭建 DAG 图、ER 图、流程图、血缘图等应用。 二、快速上手 1. 安装 npm install antv/x6 --save# oryarn add antv/x6# orpnpm add antv/x6 2. 使用 2.1 初始画布 在页面中创…