深入理解JVM四:Java内存模式与线程

JVM堆内存优化与SpringBoot配置 在当今的软件开发领域,随着业务需求的日益复杂和系统规模的不断扩大,对于Java虚拟机(JVM)和Spring Boot框架的深入理解变得尤为重要。特别是在处理大数据量和高并发场景时,如何合理地设置JVM的堆内存参数,以优化Spring Boot应用程序的性能和稳定性,成为了开发人员必须面对的问题。场景问题:假设我们正在开发一个处理大规模用户数据的在线分析平台,该平台使用Spring Boot框架构建。由于数据量巨大,系统在运行一段时间后,频繁出现内存溢出错误,导致服务不可用。 阅读详情

并发处理的广泛应用是人类充分利用计算机运算能力的最有力武器。

一、概述

计算机的运算速度与它的存储和通信子系统速度出具太大,容易浪费。
一个服务端同时对多个客户端提供服务则是另一个并发应用场景。

二、硬件的效率与一致性

如果存在一个计算任务依赖另外一个计算任务的中间结果,其顺序性并不能靠代码的先后顺序来保正——因为指令重排序优化

三、Java内存模型

Java虚拟机规范试图定义一种Java内存模型来屏蔽硬件和操作系统的内存访问差异。

3.1 主内存与工作内存

主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节。变量主要是指实例字段、静态字段和构成数组对象的元素,不包括局部变量和方法参数,因为后者是线程私有的,不会被共享。
Java内存模型规定了所有的变量都存储在主内存中,线程还有自己的工作内存,如图所示。
注意:此处的内存模型与第二章的Java堆等内存模型是不同层次的划分。
在这里插入图片描述

3.2 内存间交互操作

关于主内存与工作内存之间具体的交互协议,Java内存模型定义了8种操作来完成,保证每一种操作都是原子的。

  • lock : 作用于主内存的变量,把一个变量表示为一条线程独占的状态
  • unlock : 释放主内存变量
  • read : 把主内存的变量传输到工作内存中,以便load使用
  • load: 作用于工作内存变量,它把read操作从得到的变量值放入工作内存的变量副本中
  • use : 作用于工作内存变量,他把工作内存中一个变量的值传递给执行引擎,每当虚拟机遇到一个需要使用到变量的值的字节码指令时将会执行这个操作
  • assign(赋值) :作用于工作内存变量,他把一个从执行引擎接收到的值赋给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时将会执行这个操作
  • store : 作用于工作内存的变量,它把工作内存中一个变量的值传送到主内存中,以便随后的write使用
  • write :作用于主内存的变量,它把store操作从工作内存中得到的变量的值放入主内存的变量中。

针对这些操作,必须满足一下规则:

  • 不允许read和load、store和write操作之一单独出现,但可以不连续,中间有其他指令
  • 不允许一个线程丢弃它的最近的assign操作,即变量在工作内存中改变了之后必须把该变化同步回主内存
  • 不允许一个线程无原因(没有任何assign操作)地把数据从线程的工作内存同步回主内存
  • 一个新的变量只能在主内存中"诞生"
  • 一个变量在同一时刻只允许一条线程对其进行lock操作,但lock操作可以被同一线程执行多次,执行多次lock后需要执行相同次数的unlock才会被解锁。
  • 如果对一个变量执行lock操作,那将会清空工作内存中此变量的值,在执行引擎使用这个变量前,需要从新执行load或者assign操作初始化变量的值
  • 如果实现没lock,则不允许unlock
  • 对一个变量执行unlock操作之前,必须先把此变量同步回主内存中

3.3 对于volatile型变量的特殊规则

  • 保证变量可见性,指当一条线程修改了这个变量的值,其他线程可以立即可知
    当不符合以下两条规则,则需要加锁
    • 运算结果并不依赖变量的当前值,或者能够确保只有单一的线程修改变量的值
    • 变量不需要与其他的状态变量共同参与不变约束
  • 禁止指令重排序优化
    单例模式

3.4 原子性、可见性、有序性

  • 原子性 基本的数据类型的访问读写是具备原子性(long和double的非原子协定)
  • 可见性 volatile的特殊规则保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新
  • 有序性 Java程序的天然有效性指:如果在本线程内观察,所有操作是有序的;如果在一个线程观察另一个线程,所有的操作都是无序的。synchronized

3.5 先行发生原则

天然先行规则

  • 程序次序规则:同一线程内,按照程序控制流顺序执行
  • 管程锁定规则:一个unlock操作先行发生于后面对同一个锁的lock的操作
  • volatile变量规则: 对一个volatile变量的写操作先行发生于后面对这个变量的读操作
  • 线程启动规则: Thread对象的start()方法先行发生于此线程的每一个动作
  • 线程终止规则:线程中所有操作都先行发生于对此线程的终止检测,
  • 线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生
  • 对象终结规则: 一个对象的初始化完成(构造函数结束)先行发生于它的finalize()方法的开始
  • 传递性:如果A先行于操作B,B先行于操作C,那么就可以得出A先行于C.

四、Java与线程

并发不一定依赖多线程(多进程),但是Java的并发,大多数与线程脱不开关系。

4.1 线程的实现

进程是计算机硬件资源的分配单位,线程时CPU调度的基本单位。
实现线程主要有3种方式:

  • 内核线程实现
    直接由操作系统内核支持的线程,由内核完成线程切换,调度,映射;程序一般不使用内核线程,而是去使用内核线程的一种高级接口——轻量级进程(LWP),就是通常意义上的线程。这种轻量级进程与内核线程1:1的关系成为一对一的线程模型。这种轻量级的线程局限性在于,需要系统调用,代价高,需要在用户态和内核态切换,消耗内核资源,因此数量有限
  • 用户线程实现
    狭义上的用户线程指完全建立在用户空间的线程库上,系统内核不能感知线程存在的实现,完全在用户态完成。可以支持规模更大的线程数量,这种进程与线程之间1:N的关系称为一对多线程模型。优势在于不需要系统内核支援,劣势也在于没有系统内核的支援,所有线程操作都需要用户自己处理。
  • 用户线程加轻量级进程混合实现
  • 将内核线程与用户线程一起使用的实现方式。这种混合模式中,用户线程与轻量级进程的数量比是不定的,即为N:M的关系,这就是多对多线程模型。

Java线程的实现

JDK1.2之前是基于用户线程实现,后来基于操作系统的原生线程模型来实现。
对于Sun JDK来说,它的Windows版与Linux版都是使用一对一的线程模型实现的。

4.2 Java线程调度

线程调度是指系统为线程分配处理器使用权的过程,主要调度方式有两种,分别是:

  • 协同式线程调度
    线程的执行时间由线程本身来控制,线程执行完之后,主动通知系统切换到另外一个线程,最大好处是实现简单,坏处就是线程执行时间不可控制,如果一个线程编写有问题,会一直阻塞。
  • 抢占式线程调度
    由系统分配执行时间
    Java线程调度是系统自动完成的,Java可以设置10个级别的线程优先级,但是是通过映射到系统的原生系统,所以最终还是取决于操作系统。

4.3 状态转换

Java语言定义了5种线程线程状态,在任意一个时间点,一个进程有且只有一种状态

  • 新建 创建后尚未启动的线程
  • 运行 Runable包括了操作系统线程状态中的Running 和Ready,也就是说可能正在执行,也可能等待CPU
  • 无限期等待 不会被分配CPU,要等待其他线程的显示唤醒
  • 限期等待 不会被分配CPU,不过无需等待其他线程显示唤醒,在一定时间后由系统自动唤醒
  • 阻塞 与等待状态的区别是,阻塞状态在等待获取一个排他锁,在程序等待进入同步区域的时候,线程将进入这种装态
  • 结束 线程已经结束执行
深入理解Java享元模式及其线程安全实践 享元模式(Flyweight Pattern)是一种结构型设计模式,通过共享对象来减少内存占用,从而高效支持大量细粒度的对象。其核心思想是分离对象的内部状态(可共享)和外部状态(不可共享),通过共享内部状态来避免重复创建对象。// 外部状态由参数传入。 阅读详情

相关推荐

避坑指南:群晖DSM 7.X挂载NTFS硬盘,为什么你的SATA口不行?从原理到实战一次讲清

本文深入解析群晖DSM 7.X系统挂载NTFS硬盘的底层原理与实战排查方法,揭示SATA接口权限配置的关键参数(如esataportcfg和internalportcfg),并提供安全修改端口配置的详细步骤。针对不同型号群晖NAS的配置差异,给出替代方案与常见故障排查技巧,帮助用户解决NTFS硬盘挂载问题。

weixin_26757925的博客 256

【JVM】JVM内存模型(详细)

JVM内存模型(详细)

酷酷的馫博客 5万+

uni-app蓝牙MTU设置失效探因:从20字节限制到跨设备兼容性实战

本文深入探讨了uni-app蓝牙开发中MTU设置失效的常见问题,特别是20字节限制的成因及解决方案。通过分析设备兼容性、蓝牙协议栈特性和系统版本差异,提供了智能延迟策略、设备特征检测和渐进式MTU提升等实战方案,帮助开发者优化蓝牙数据传输效率。

weixin_29289821的博客 287

JVM 线程模型

引言 本文着重介绍 JVM 线程模型相关的内容。 线程模型 我们知道,线程是比进程更轻量级的调度执行单元,而主流的操作系统都提供了线程的实现,Java 语言则提供了不同硬件和操作系统平台下对线程操作的统一抽象,每个执行了 start 函数且未结束的 java.lang.Thread 类实例就代表了一个线程。要想实现线程,主要有 3 种方式:使用内核线程实现、使用用户线程实现、使用用户线程加轻量级进程混合实现。 可选方案 使用内核线程实现 内核线程(Kernel-Level Thread, KLT)就是直接

贝克街的流浪猫 1167

SAP WM模块配置详解

1.给工厂/存储地点分配仓库编码 功能说明 配置路径 IMG>企业结构>分配>分配后勤执行>给工厂/存储地点分配仓库编码 业务示例 配置步骤 2.定义仓库号码控制参数 功能说明 配置路径 IMG>后勤执行>仓库管理>主数据>主数据>定义仓库号码控制参数 业务示例 配置步骤 3.定义编码范围 功能说明 配置路径 IMG>后勤执行>仓库...

weixin_40672823的博客 2万+

IAR编译相同工程生产hex文件checksum不一致问题

IAR Checksum

xqw19891201的博客 1382

彻底理解JVM内存模型

JVM内存模型。

西岭千秋雪的博客 2070

基于dify平台批量分析excel格式信息

如何以表格形式批量输入一些信息,然后让大模型以对话应用形式逐条进行推理分析?请逐行分析以下数据,给出推理结果:{{input}}这里提供一个分步解决方案,结合。

knightissocool的博客 8008

Java——内存模型详解!

Java内存模型是一种抽象的规则或规范,定义了程序中存在竞争现象的对象(包括实例字段、静态字段和数组对象,不包括局部变量,形式参数;后者是线程私有,不存在竞争问题)的访问方式。如果我们要想深入了解Java并发编程,就要先理解好Java内存模型。Java内存模型定义了多线程之间共享变量的可见性以及如何在需要的时候对共享变量进行同步。JVM通过Java内存模型,屏蔽掉不同硬件和操作系统的内存访问差异,实现各种平台具有一致的并发效果。

m0_64363449的博客 2195

PostgreSQL 异常排查:读取流时发生异常 (x80004005)

通过以上步骤,您应该能够解决在 .NET Core 中与 PostgreSQL 数据库进行交互时出现异常 (x80004005) 的问题。确保数据库连接正确,查询语句准确,并使用兼容的驱动程序版本。如有必要,可以捕获异常并查看详细的错误信息,以便更好地排查问题。在使用 .NET Core 开发应用程序时,如果在与 PostgreSQL 数据库进行交互时遇到异常,例如在读取数据流时发生异常 (x80004005),我们需要进行排查和修复。另外,还可以尝试捕获异常并打印异常信息,以便更好地了解问题所在。

XwlyVue的博客 1621

出现Command ‘vim‘ is available in the following places,vim: command not found等解决方法

内置命令无法识别,说明系统变量有误,导致无法识别,既然系统变量有误,将其注释或者更改为正确的即可,但是现在打不开,又怎么注释掉。替换vim来打开编辑,打开之前错误的全局变量文件,发现变量有误,要么注释要么改为。系统变量有全局变量(通过命令行printenv或者echo)和局部变量。对应通过vim修改错误的变量文件,不然source也无法让配置文件生效。本身vim是系统内置的命令,连vim都出现问题。修改为正确的即可,之后还需要重启服务器,使用。之后即可成功,通过即可查看命令是否有写入。...

码农研究僧的博客 5883

【JVM】JVM内存模型详解

JVM屏蔽了与操作系统平台相关的信息,使得Java程序只需要生成在Java虚拟机上运行的目标代码(字节码),就可在多种平台上不加修改的运行,这也是Java能够“一次编译,到处运行的”原因。方法区存储的内容有:类型信息(比如类全称、父类全称)、域信息(域名称、域修饰符private等)、方法信息(方法名称、方法修饰符、返回类型等)、字面量(字面量包括文本字符串、八种基本类型的值 、被声明为final的常量等)。Java虚拟机栈是当前线程在执行方法时存储所需的数据、指令、返回地址的一种栈结构(先进后出)。

Money、坤的博客 1万+

educoder实训——计算几何形状的表面积与体积

educoder python实训

qq_41234663的博客 1230

深入理解多线程编程和 JVM 内存模型

本文将探讨多线程编程的基本概念,JVM 内存模型,以及常见的多线程编程模式。程序员需要深入理解多线程的概念、JVM 内存模型,以及常见的多线程编程模式,来编写安全和高效的多线程应用程序。不同的应用场景和需求可能需要不同的多线程编程模式和技术,因此不断学习和实践是非常重要的。进程是操作系统中的一个独立的执行单元,拥有自己的内存空间、文件描述符、以及系统资源。线程是进程中的执行单元,多个线程可以共享同一个进程的内存和资源。每个线程都拥有自己的栈,用于存储方法的局部变量和方法调用的信息。它也是多线程共享的区域。

学IT,找陈寒 1万+

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

【JVM】Java堆 :深入理解内存中的对象世界

Java堆是Java虚拟机管理的内存中最大的一块区域,用于存放对象实例。堆是由垃圾收集器管理的主要区域,它负责对象的创建、存储、和回收。在Java程序中,通过new关键字创建的对象都被分配到堆中。Java堆是Java虚拟机中最大的一块内存区域,负责存储动态创建的对象实例。了解Java堆的作用、特点以及对象的生命周期对于编写高效、健壮的Java程序至关重要。通过本文的介绍,希望读者能更深入地理解Java堆在内存管理中的重要性。

double222222的博客 2186

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

《深入理解JVM》实战笔记(四):Java内存模型与多线程

短任务,高吞吐量 | | ScheduledThreadPool | 支持定时/周期任务 | 定时调度 | | WorkStealingPool | 任务窃取,多核优化 | CPU密集型并行计算 |在单线程中,重排序不会影响结果,但在多线程环境下,可能导致不可预期的行为。线程对变量的操作(如读取、赋值)必须在工作内存中进行,无法直接访问主内存。本文深入剖析JMM的核心原理、多线程的底层实现以及实际开发中的优化策略。Java内存模型(JMM)定义了线程与内存之间的抽象关系:所有共享变量存储在。

weixin_39899039的博客 896

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

深入理解Java内存模型及其作用

当问到 Java 内存模型的时候,一定要注意,Java 内存模型(Java Memory Model,JMM)它和 JVM 内存布局(JVM 运行时数据区域)是不一样的,它们是两个完全不同的概念。Java 内存模型(Java Memory Model,简称 JMM)是一种规范,它定义了 Java 虚拟机(JVM)在计算机内存(RAM)中的工作方式,即规范了 Java 虚拟机与计算机内存之间是如何协同工作的。

qq_35716689的博客 1万+

深入理解 JVM(Java 虚拟机)

从简图中可以看出 JVM 的堆内存分为新生代和老年代,新生代和老年代的内存占比默认是 1:2,JVM 的代指的是不同生命周期的对象,不同生命周期对象又存在不同的区域中,不同区域的内存被定义为“代”,这样做的目的是提升垃圾回收的效率,因为有了“代”的概念就可以针对不同的“代”执行不同的垃圾回收策略。我们知道 Java 栈是 Java 线程执行方法的内存模型,用来存储方法执行时候的局部变量表、操作数栈、动态链接、方法出口,下面我们分别来对局部变量表、操作数栈、动态链接、方法出口进行详细说明。

weixin_42118323的博客 1034

深入理解JVM:Java语言与JVM关系

在那个电闪雷鸣,群鸟环绕的夜晚,一个不为人知的语言Oak诞生了,此时正值1991年4月份,气温舒适,百花齐放。然而Oak的诞生并没有得到人们的关注,直到1995年5月23号,Oak决定正是更名为Java,并喊出了 “Write Once,Run Anywhere”(一次编写,随处运行)的口号,真是一语惊天雷,从此震乾坤。 Java语言作为世界上最为流行且用户使用量最多的语言,由当时的懵懂少年,已然成为了现在的稳重青年。他怀揣梦想,肩负使命,不断在信息化的时代披荆斩棘,破浪前行。一幅图足以说明其成长历史。.

weixin_30484149的博客 907

JVM内存配置参数

题目 对于JVM内存配置参数: -Xmx10240m -Xms10240m -Xmn5120m -XXSurvivorRatio=3 ,其最小内存值和Survivor区总大小分别是()   A 5120m,1024m   B 5120m,2048m   C 10240m,1024m   D 10240m,2048m 答案解析 正确答案是:D -Xmx:最大堆大小 -Xms...

凡是过往,皆为序章 1万+

Java底层原理:深入理解JVM内存管理机制

在Java开发中,JVM(Java虚拟机)的内存管理机制是理解Java性能优化和故障排查的关键。本文将深入探讨JVM内存管理的底层原理,帮助你更好地理解Java应用的运行机制。

weixin_66924704的博客 927

深入理解JVM内存屏障

内存屏障是Java并发编程的“幕后英雄”。正确使用volatile等关键字;避免因内存可见性和指令重排序导致的隐蔽Bug;在高性能场景下做出合理取舍。终极建议:在多数业务场景中,优先使用包中的线程安全工具类,而非手动管理内存屏障。

ocean_this_is_it的博客 1231

深入理解JVM-- JAVA内存模型、对象的访问模式(一)

深入理解JVM-- JAVA内存模型、对象的访问模式 一、JAVA内存模型 ​ 开发离不开内存的支持,所以在开发者使用Java进行程序开发的过程之中,如果要想实现程序的高效运行效果,那么必须对整个Java的内存体系有所掌握。而如果要想理解整个Java的内存体系,那么首先必须清楚Java程序的执行流程。 ​ java内存模型 ​ 程序的执行步骤: 按照功能的要求编写一个*.java的源程序,...

Happy祥子的博客 283

Java 程序到底是怎么跑起来的?——深入理解 JVM 架构与执行原理

JVM,全称 Java Virtual Machine(Java 虚拟机),是一个运行在计算机上的程序,用来执行 Java 字节码(.class 文件)。JVM 本质上是一个进程,而不是单纯的内存空间。当你运行 Java 程序时,实际上是启动了 JVM 进程,它负责在运行时将字节码转换为机器码,并管理程序的执行环境。阶段JVM 所在位置说明程序启动前磁盘上(如 Windows 的 java.exe、Linux 的 java、动态库 libjvm.so 等)

m0_73341242的博客 954

java工程师面经,深入JVM--JVM内存结构,【金三银四】

在开头跟大家分享的时候我就说,面试我是没有做好准备的,全靠平时的积累,确实有点临时抱佛脚了,以至于我自己还是挺懊恼的。(准备好了或许可以拿个40k,没做准备只有30k+,你们懂那种感觉吗)如何准备面试?1、前期铺垫(技术沉积)程序员面试其实是对于技术的一次摸底考试,你的技术牛逼,那你就是大爷。大厂对于技术的要求主要体现在:基础,原理,深入研究源码,广度,实战五个方面,也只有将原理理论结合实战才能把技术点吃透。

2301_76190858的博客 977
上一篇: 深入理解JVM二:垃圾收集器与内存分配策略
下一篇: 深入理解JVM五:线程安全与锁优化
张小飘
博客等级 码龄11年 9粉丝 41原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值