当前位置: 首页 > news >正文

深入解析Java内存模型

一、背景

并发编程本质问题是:CPU、内存以及IO三者之间的速度差异。CPU速度快于内存、内存访问速度又远远快于IO,根据木桶理论,程序性能取决于最慢的操作,即IO操作。这样会出现CPU和内存交互时,CPU性能无法被充分利用,内存与IO交互时,内存性能也存在部分损耗,单方面提升CPU或内存的性能是无效的。为了提升CPU或内存的利用率,需要平衡三者的速度差异,计算机系统结构操作系统以及编译程序都做出了贡献,主要体现为:

1. 计算机体系结构:为CPU增加了缓存,均衡和内存的速度差异;
2. 操作系统:增加了进程和线程,便于分时复用CPU,均衡CPUIO设备的速度差异;
3. 编译程序:优化CPU指令的执行顺序,使得缓存被更加合理的利用。

上述方案虽然很大程度上解决了程序的性能问题,但也带来了许多隐藏的并发问题,主要为:可见性问题原子性问题以及有序性问题

可见性问题:

定义:一个线程对共享变量的修改,另外一个线程能够立刻看到,即可见性
导致原因:CPU缓存
详情解析:在多CPU时代,每个CPU都有自己的缓存,当多个CPU缓存同一份共享变量的数据时,线程A修改了共享变量,但修改目前只在CPU的缓存生效,其他CPU缓存还未来得及获取新修改的数据,线程B读取共享变量,读取的数据是老数据,存在数据不一致问题。

原子性问题:

定义:一个或多个操作在CPU执行过程中不被中断的特性,即原子性
导致原因:多线程上下文切换
详情解析:多线程底层执行是按照时间片来执行的,进行任务切换时,针对的是单个CPU指令,仅能保证单个CPU指令的原子性。而高级语言的一条语句,往往是由多个CPU指令完成。例如count += 1,至少需要三条指令:
1. 首先,将变量count加载到对应CPU的寄存器中;
2. 其次,在寄存器中执行 +1 操作;
3. 最后,将结果写入到内存中
若是线程A执行完指令1后,切换到线程B来执行 count += 1操作,线程B操作后count为2,但线程A中保存的count值仍是1,导致最后的结果为2,实际上应该为3。

Java中的原子操作有哪些:
1.longdouble之外的基本类型(int, byte, boolean, short, char, float)的赋值操作;针对long操作,直接拆分成两个32位的写入操作。
2. 所有引用reference的赋值操作;
3. java.concurrent.Atomic.*包中所有类的原子操作。
原子操作 + 原子操作 != 原子操作【原子性对比:】
synchronized:不可中断锁,适合竞争不激烈,可读性好
Lock: 可中断,多样化同步,竞争激烈时能维持常态
Atomic: 竞争激烈时能维持常态,比Lock性能好;只能同步一个值

有序性问题:

定义:有序性是指按照代码的先后顺序来执行,但编译器为了优化性能,可能会改变代码的执行顺序。例如:i = 1; j = 2 变成 j = 2; i = 1
导致原因:编译优化
详情解析:在Java领域存在一个双重检查创建单例对象的场景,创建对象JVM底层分为三个步骤:
1. 分配内存空间;
2. 在内存上初始化对象;
3. 将对象地址赋值给实例变量
此时进行了编译优化,将1,2,3变成了1,3,2。那么就会出现多线程访问时,某些线程获取的对象为null,出现空指针问题。

因此,为了解决出现的可见性、原子性以及有序性问题,Java给出了一套解决方案,即Java Memory Model,简称JMM

二、Java内存模型

为了解决可见性和有序性,直观上可以理解:禁用缓存和编译优化,但程序的性能就无法保证。理想方案是:开发者按需禁用缓存和编译优化,因此Java做了两个方面的工作:

  1. 定义一种抽象计算机模型
  2. 定义一系列规则,来保证可见性和有序性。

2.1 定义

抽象计算机模型:JMM定义了线程和主内存之间的抽象关系:线程之间共享的变量存储在主内存中,每个线程有一个私有的本地内存,每个本地内存中存储了共享变量的副本。其中本地内存[工作内存]是一个抽象概念,底层对应着缓存、寄存器以及硬件和编译器优化等。主内存和工作内存之间的规范为:
在这里插入图片描述

  1. 所有的共享变量都存储于主内存:这里的变量值是实例变量、类变量以及数组,因为堆和方法区是线程共享的。(局部变量属于线程私有,不存在线程安全问题)
  2. 工作内存:每一个线程有自己的工作内存,工作内存中保留了被多个线程使用的变量的工作副本
  3. 线程不能直接读写主内存中的变量
    ① 只能操作自己的工作内存中的变量,
    ② 然后再同步到主内存中
  4. 工作内存的屏蔽性:不同线程之间不能直接访问对方工作内存中的变量,线程之间的值传递需要通过主内存来完成。(可见性问题的罪魁祸首)

一系列规则:volatile、synchronized和final三个关键字,以及六项Happens-Before规则。

2.2 规则

Happens-Before规则指的是:前面一个操作结果对后续操作是可见的。下面为详细的规则:

  1. 单线程规则:一个线程中的每个操作,happens-before于该线程的任意后续操作;
  2. 监视器锁规则(synchronized):对一个锁的解锁,happens-before于随后对这个锁的加锁;
  3. volatile变量规则:对一个volatile修饰的变量的写,happens-before于随后对这个变量的读;
  4. 传递性:如果A happens-before B、 B happens-before C、则A happens-before C;
  5. 线程start启动规则:主线程A启动子线程B后,子线程B能够看到主线程在启动子线程B前的操作结果;
  6. 线程join()规则: 主线程A等待子线程B完成,当子线程B完成后,主线程能够看到子线程的操作结果。
  7. final规则: 通过final修饰变量,告诉编译器着变量是不会发生改变的,可以尽情优化。

三、总结

上述解决了可见性和有序性问题,原子性问题通过互斥锁可以完美解决。

相关文章:

深入解析Java内存模型

一、背景 并发编程本质问题是:CPU、内存以及IO三者之间的速度差异。CPU速度快于内存、内存访问速度又远远快于IO,根据木桶理论,程序性能取决于最慢的操作,即IO操作。这样会出现CPU和内存交互时,CPU性能无法被充分利用…...

python使用国内镜像源

使用格式 格式为:pip install 库名 -i 镜像地址(注意空格的存在) pip install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple 推荐的镜像源: 清华大学(推荐):https://pypi.tuna.tsing…...

【动态规划】代码随想录算法训练营第四十六天 |139.单词拆分,关于多重背包,你该了解这些! ,背包问题总结篇!(待补充)

139.单词拆分 1、题目链接:. - 力扣(LeetCode) 2、文章讲解:代码随想录 3、题目: 给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词…...

WordPress建站入门教程:如何选择和设置固定链接结构?

我们成功搭建好WordPress网站后,发布的文章对应的URL地址默认是使用“日期和名称型”,即是网站域名跟着的是年月日,最后是文章标题,如http://www.yigujin.com/2024/03/06/免费响应式WordPress博客主题JianYue/ 为了让我们的文章U…...

一款好用的AI工具——边界AICHAT(三)

目录 3.23、文档生成PPT演示3.24、AI文档翻译3.25、AI翻译3.26、论文模式3.27、文章批改3.28、文章纠正3.29、写作助手3.30、文言文翻译3.31、日报周报月报生成器3.32、OCR-DOC办公文档识别3.33、AI真人语音合成3.34、录音音频总结3.35、域方模型市场3.36、模型创建3.37、社区交…...

编程示例: 矩阵的多项式计算以javascript语言为例

编程示例: 矩阵的多项式计算以javascript语言为例 国防工业出版社的《矩阵理论》一书中第一章第8个习题 试计算2*A^8-3*A^5A^4A^2-4I A[[1,0,2],[0,-1,1],[0,1,0]] 代码如下 <html> <head> <title> 矩阵乘法 </title> <script srcset.js ><…...

project generator 简单使用

文章目录 1 progen 资源2 使用简介2.1 安装2.2 添加 target&#xff08;可选&#xff09;2.3 替换 CMake 模板&#xff08;可选&#xff09;2.4 创建 progen 项目 3 总结 1 progen 资源 0&#xff09;简介&#xff1a;progen&#xff08;project-generator&#xff0c;项目生成…...

C语言 —— 图形打印

题目1&#xff1a; 思路&#xff1a; 如果我们要打印一个实心正方形&#xff0c;其实就是一个二维数组&#xff0c;i控制行&#xff0c;j控制列&#xff0c;行列不需要控制&#xff0c;arr[i][j]直接打印星号即可。 对于空心正方形&#xff0c;我们只需要控制行和列的条件&…...

Python基础学习(11)常用模块

文章目录 一、time二、random三、os四、sys五、json补充1&#xff1a;JSON字符串补充2&#xff1a;JSON字符串和字典的区别 六、hashlib Python基础学习(1)基本知识 Python基础学习(2)序列类型方法与数据类型转换 Python基础学习(3)进阶字符串(格式化输出) Python基础学习(4)散…...

嵌入式学习37-TCP并发模型

TCP并发模型: 1.TCP多线程模型: 缺点: 1.创建线程会带来 资源开销 2.能够实现的 并发量 比较有限 2.IO模型: 1.阻塞IO: 没有…...

C语言字符函数和字符串函数

前言 今天这篇博客咱们一起来认识一些特殊的函数&#xff0c;在编程的过程中&#xff0c;我们经常要处理字符和字符串&#xff0c;为了方便字符和字符串&#xff0c;C语言提供了一些库函数&#xff0c;让我们一起看看这些函数都有什么功能吧&#xff01;&#xff01;&#xff0…...

Go语言必知必会100问题-22 空切片与nil切片有区别吗?

空切片与nil切片有区别吗&#xff1f; 很多开发人员经常混淆nil切片和空切片,不清楚什么时候使用空切片什么时候使用nil&#xff0c;而有些库函数又对这两者使用进行了区分。下面先来看看它们的定义。 空切片是length为0的切片当切片等于nil时为nil切片 下面是几种不同空切片…...

【C++进阶】C++多态概念详解

C多态概念详解 一&#xff0c;多态概念二&#xff0c;多态的定义2.1 多态构成的条件2.2 什么是虚函数2.3 虚函数的重写2.3.1 虚函数重写的特例2.3.2 override和final 2.4 重载和重写&#xff08;覆盖&#xff09;和重定义&#xff08;隐藏&#xff09;的区别 三&#xff0c;抽象…...

Python 导入Excel三维坐标数据 生成三维曲面地形图(面) 2、线条平滑曲面但有间隔

环境和包: 环境 python:python-3.12.0-amd64包: matplotlib 3.8.2 pandas 2.1.4 openpyxl 3.1.2 scipy 1.12.0 代码: import pandas as pd import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from scipy.interpolate import griddata imp…...

前端精准测试调用链路分析

精准测试在评估需求的测试范围时&#xff0c;需要评估一下代码的影响范围&#xff0c;这个范围有两部分&#xff1a;一是需求直接修改的代码&#xff1b;二是修改代码影响到的功能模块。代码影响到的功能一般是通过调用链路分析来实现的&#xff0c;java和kotlin代码可以由java…...

Objective-C blocks 概要

1.block的使用 1.1什么是block&#xff1f; Blocks是C语言的扩充功能&#xff1a;带有自动变量&#xff08;局部变量&#xff09;的匿名函数。 “带有自动变量”在Blocks中表现为“截取自动变量" “匿名函数”就是“不带名称的函数” 块&#xff0c;封装了函数调用及调用…...

Linux操作系统-07-Linux安装应用

一、使用rpm安装应用&#xff08;不推荐&#xff09; 先下载到本地&#xff0c;以.rpm文件名结尾&#xff0c;下载完成后&#xff0c;再安装 rpm -qa | grep mysql #查询当前系统是否有下载过mysql包 先上传mysql的rpm安装包到linux的opt目录 安装 rpm -ivh …...

DevOps实战:Docker、Kubernetes与Jenkins的完美融合

DevOps与容器化技术&#xff1a;Docker、Kubernetes和Jenkins 引言 在软件开发领域&#xff0c;DevOps文化和容器化技术已经成为当今最热门的话题之一。DevOps的目标是缩短开发和运维之间的距离&#xff0c;提高软件交付的速度和质量。而容器化技术&#xff0c;如Docker和Kub…...

Python面向对象——程序架构

需求 创建图形管理器 -记录多种图形(圆形、矩形.) --提供计算总面积的方法&#xff0c; 要求:增加新图形&#xff0c;不影响图形管理器 测试: 创建图形管理器&#xff0c;存储多个图形对象。 通过图形管理器&#xff0c;调用计算总面积方法 思路 ​​​​​​​ 代码 # ------…...

springboot单体项目链路日志跟踪及接口耗时

最近接触一个新的传统项目,在联调过程中,查看日志特别不方便,既无trackId,即无接口耗时,所以写了该博客。话不多说,直接上代码 1、实体类user package com.yk.domain;import lombok.Data;@Data public class User {private Long id;private String username;private St…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

docker 部署发现spring.profiles.active 问题

报错&#xff1a; org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

基于Java+MySQL实现(GUI)客户管理系统

客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息&#xff0c;对客户进行统一管理&#xff0c;可以把所有客户信息录入系统&#xff0c;进行维护和统计功能。可通过文件的方式保存相关录入数据&#xff0c;对…...

Windows安装Miniconda

一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用

在工业制造领域&#xff0c;无损检测&#xff08;NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统&#xff0c;以非接触式光学麦克风技术为核心&#xff0c;打破传统检测瓶颈&#xff0c;为半导体、航空航天、汽车制造等行业提供了高灵敏…...