【JUC-JMM】Java Memory Model Java内存模型

Java内存模型--JMM

  • 一、JMM是什么?
  • 二、Happens-Before原则
  • 三、JMM有什么用?

一、JMM是什么?

JMM,全拼Java Memory Model,翻译过来就是Java内存模型。 那么,我们不禁思索,Java内存模型有什么用,是用来做什么的呢?

带着这个问题,学过计算机组成原理的同学应该知道,CPU中寄存器的访问速度很快,内存的访问速度相较来说,比较慢,为了协调CPU中寄存器与内存的访问速度差异,设计了L1,L2,L3三级缓存,如下(以笔者电脑为例):
在这里插入图片描述

有了缓存之后,我们尽可能操作缓存中的数据,接下来问题来了,如果缓存中的数据被修改了,会造成缓存与内存中数据不一致。为了解决这个问题,提出了缓存一致性策略,这个东西不是本文的重点,文末会给出CPU缓存一致性的方法。

整体效果图如下:

每个CPU核有自己独立的L1,L2 缓存,共用L3 缓存,通过缓存一致性将L3缓存与主存中的数据保持一致。

但是,不同系统下的指令集与时钟都不一致,Java语言要能够兼容不同系统下的读写,Java完全可以这么做:Java-windowsjava-linuxjava-macos,发行多个版本,然后维护多个版本,但实际上并没有这么做,而是做了一种约定, 用于屏蔽底层不同操作系统与硬件之间的读写差异。 注意,我们说的约定,这个约定就是JMM,也就是Java内存模型。

Java内存模型有三个特点:

  1. 可见性:一个线程对共享变量的修改,其他线程立即可见。(线程A修改数据之后写回内存,线程B读取)
  2. 原子性:一个线程在操作的时候不允许其他线程打断,这个操作要么都完成,要么都不完成。
  3. 有序性:只要程序最终结果与串行执行结果一致,那么将允许指令重排序。有序性只保证单个线程的正确性

Q:为什么说的是线程呢?
A:上面图画的明明时CPU,其实是一个意思,一个CPU在一个时间片内只能执行一个线程。

Q:为什么是共享变量而不是主存?
A:Java中变量存储在主存中。

上面图片抽象成Java多线程如下:
在这里插入图片描述

JMM规定,任何线程不能直接操作主内存中的变量,应该先将主内存的变量复制一份到本地独立栈空间内,然后进行操作,操作完之后,将变量写回主内存,线程B再读取主存中的值就是最新的了。

上面操作只能保证单线程下正确访问,多线程并发下不能保证一致性。

JMM定义了 8 8 8 中操作来完成内存间交互:

操作说明
lock作用于主内存变量,把一个变量标识为一个线程独占的状态
unlock作用于主内存变量,把处于锁定的变量释放出来
read读,作用于主内存变量,将主内存变量读到线程本地内存中
load加载,将read操作读到的变量存入本地内存的副本中
use作用于本地内存变量,将变量的值交给执行引擎
assign作用于本地内存变量,将从执行引擎读到的值赋值给本地内存变量
store存储,作用于主内存,将本地内存变量的值送到主存中
write写入,作用于主内存,store的值赋值给主内存变量

后面六个是原子操作,但是组合起来不是原子操作,例如read/load组合起来不是原子的,read的中间可能有别的线程再read/load

例如:两个线程执行同一个代码快:

x = 1
x ++

线程A, B分别读取 1 1 1 到自己的本地内存中,A先执行了x++,将主存中值修改为2,但是线程B此时并不知道,因此它也执行了x++,主存中的值还是2,与我们想象中的3不同。

二、Happens-Before原则

Happens-Before原则定义了前一种操作的结果对后一种操作的结果是可见的。
比如说:操作1 happens-before 操作2, 即使操作1和操作2不在一个线程内执行,JMM也会保证操作1的结果对操作2是可见的。
具体来说, happens-before有八个原则:

  1. 次序原则:一个线程内,写在前面的操作先行发生于写在后面的操作,例如x=3, y=x+1, 第一条语句肯定先行发生于第二条语句。
  2. 锁定原则:解锁操作 happens-before加锁操作
  3. volatile原则:对一个volatile变量的写操作,一定先行发生于对该变量的读操作。
  4. 传递原则:A happens-before B, B happens-before C, 那么 A happens-before C
  5. 线程启动原则:线程对象的start方法先行发生于线程内的具体操作。
  6. 线程中断规则:interrupt方法先行发生于isInterrupted()为true的代码块内的方法。
  7. 线程终止规则:线程内所有操作都优先发生于线程终止操作。可以用isAlive判断是否存活
  8. 对象终结规则:一个对象初始化完成先行发生于它的finalize()方法

JMM抽象了这个原则来解决指令重排序,有了这个原则,不需要所有的变量都加上volatile 来禁止指令重排序了,简化代码编辑

三、JMM有什么用?

有了JMM规范,我们不需要在任何变量前都加volatilesynchronizedlock,提高系统执行效率。

JMM高并发场景下三个特性的落地实现:

  • 原子性:lock, unlock, synchronized保证了原子性
  • 可见性:synchronized, lock, unlockvolatile保证了数据的可见性。
  • 有序性:指令重排序可以保证串行语义一致,但是没有义务保证多线程间的语义也一致 ,所以在多线程下,指令重排序可能会导致一些问题。·volatile关键字可以禁止指令重排序。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringAI:Java 开发的智能新利器

一、SpringAI 简介 随着人工智能技术的飞速发展,越来越多的开发者开始探索如何将 AI 能力集成到现有的应用中来提升产品的智能化水平。Spring AI 正是为 Java 开发者提供的一款强大的 AI 框架,使得这一集成过程变得前所未有的简单和高效。 本文将深入探…

在Excel中处理不规范的日期格式数据并判断格式是否正确

有一个Excel表,录入的日期格式很混乱,有些看着差不多,但实际多一个空格少一个字符很难发现,希望的理想格式是 1980-01-01,10位,即:“YYYY-mm-dd”,实际上数据表中这样的格式都有 19…

【我在CSDN成长】我的五周年创作纪念日

感叹 五年的时光匆匆而过, 像一阵风,拂过岁月的湖面, 泛起层层涟漪,又悄然离去。 曾经的欢笑与泪水, 那些奋斗的日夜, 如同电影般在脑海中放映, 却已成为遥远的回忆。 五年,说长不长…

Jmeter中的定时器

4)定时器 1--固定定时器 功能特点 固定延迟:在每个请求之间添加固定的延迟时间。精确控制:可以精确控制请求的发送频率。简单易用:配置简单,易于理解和使用。 配置步骤 添加固定定时器 右键点击需要添加定时器的请求…

BERT 详解

BERT简介 BERT(Bidirectional Encoder Representations from Transformers)是由 Google 在 2018 年提出的一种预训练语言模型。BERT 在自然语言处理(NLP)领域取得了重大突破,因为它能够有效地捕捉文本的上下文信息&am…

macos 14.0 Monoma 修改顶部菜单栏颜色

macos 14.0 设置暗色后顶部菜单栏还维持浅色,与整体不协调。 修改方式如下:

数据库-MySQL-Dynamic-Datasource源码解析

文章目录 前言一、简介二、整体流程三、核心解析四、总结 前言 多数据源的应用在日常项目中也是很常见的场景。 dynamic-datasource的功能,用起来的确很方便,只需要一个DS注解,加上一些简单的配置即可完成多数据源的切换。究竟是怎么做到的…

YB2503HV:高效率降压IC,助力电动车、太阳能设备等领域的能源转换

今天我要向大家介绍一款引人注目的产品—— YB2503HV 100V 3A SOP8内置MOS 高效率降压IC。这款单片集成芯片具备可设定输出电流的开关型降压恒压驱动器功能,可广泛应用于电动车、太阳能设备、电子电池充电等领域。让我们一起来看看它的特点和应用吧! 首先…

架构-微服务架构

文章目录 前言一、系统架构演变1. 单体应用架构2. 垂直应用架构3. 分布式架构4. SOA 架构5. 微服务架构 二. 微服务架构介绍1. 微服务架构的常见问题2. 微服务架构的常见概念3. 微服务架构的常见解决方案4. 解决方案选型 三. Spring Cloud Alibaba介绍1. 主要功能2. 组件 前言 …

【一个简单的整数问题2——线段树】

题目 代码 下面的两个代码的区别在于modify的分类&#xff0c;modify最简单的分类方式是存在性分类&#xff0c;另一种类似某些query采用的三段式分类&#xff0c;详细见代码 存在性 #include <bits/stdc.h> using namespace std; using ll long long; const int N 1…

通用网络安全设备之【防火墙】

概念&#xff1a; 防火墙&#xff08;Firewall&#xff09;&#xff0c;也称防护墙&#xff0c;它是一种位于内部网络与外部网络之间的网络安全防护系统&#xff0c;是一种隔离技术&#xff0c;允许或是限制传输的数据通过。 基于 TCP/IP 协议&#xff0c;主要分为主机型防火…

如何启动 Docker 服务:全面指南

如何启动 Docker 服务:全面指南 一、Linux 系统(以 Ubuntu 为例)二、Windows 系统(以 Docker Desktop 为例)三、macOS 系统(以 Docker Desktop for Mac 为例)四、故障排查五、总结Docker,作为一种轻量级的虚拟化技术,已经成为开发者和运维人员不可或缺的工具。它允许用…

构建英语知识网站:Spring Boot框架解析

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

Android mk/bp构建工具介绍

零. 前言 由于Bluedroid的介绍文档有限&#xff0c;以及对Android的一些基本的知识需要了(Android 四大组件/AIDL/Framework/Binder机制/JNI/HIDL等)&#xff0c;加上需要掌握的语言包括Java/C/C等&#xff0c;加上网络上其实没有一个完整的介绍Bluedroid系列的文档&#xff0…

2022 年中高职组“网络安全”赛项-海南省省竞赛任务书-1-B模块B-1-Windows操作系统渗透测试

前言 本章节我将带领大家一起重新模拟操作一次Windows渗透测试模块&#xff0c;并加固的流程。 任务概览 环境部署 我的实验复现环境&#xff1a; 服务器Windows server 2008 R2 攻击机Kali Linux 场景操作系统Windows 7 额外还有台交换机支持&#xff1a; 这里我使用的是…

如何搭建一个小程序:从零开始的详细指南

在当今数字化时代&#xff0c;小程序以其轻便、无需下载安装即可使用的特点&#xff0c;成为了连接用户与服务的重要桥梁。无论是零售、餐饮、教育还是娱乐行业&#xff0c;小程序都展现了巨大的潜力。如果你正考虑搭建一个小程序&#xff0c;本文将为你提供一个从零开始的详细…

根据实验试要求,打通隧道连接服务器上的数据库,前端进行数据调用。

1.背景介绍 数据库布置在了工大实验试K80服务器上&#xff0c;本地属于外网无法直接访问校园内网。需要打通隧道&#xff0c;通过堡垒机进行服务器的访问。获取到数据库数据进行前端展示。 2.打通隧道 访问指令&#xff1a; 我选择使用Xshell打通隧道。优点&#xff1a;凭证…

使用 exe4j 将 Spring Boot 项目打包为 EXE 可执行文件

使用 exe4j 将 Spring Boot 项目打包为 EXE 可执行文件 文章目录 使用 exe4j 将 Spring Boot 项目打包为 EXE 可执行文件什么是 exe4j准备工作打包 Spring Boot 项目为 EXE 文件1.启动 exe4j2. 选择项目类型3. 配置项目名称和输出目录4. 配置项目类型或可执行文件名称5. java配…

24/11/26 视觉笔记 通过特征提取和透视变换查找对象

在本节中我们将检测和跟踪任意大小的对象&#xff0c;这些对象可能是在不同角度或者在部分遮挡的情况下观察到的。 为此我们将运用特征描述子&#xff08;Feature Descriptor&#xff09;&#xff0c;这是捕获感兴趣对象的重要属性的一种方式。我们这样是为了即使将对象嵌入繁…

【K8S问题系列 |18 】如何解决 imagePullSecrets配置正确,但docker pull仍然失败问题

如果 imagePullSecrets 配置正确&#xff0c;但在执行 docker pull 命令时仍然失败&#xff0c;可能存在以下几种原因。以下是详细的排查步骤和解决方案。 1. 检查 Docker 登录凭证 确保你使用的是与 imagePullSecrets 中相同的凭证进行 Docker 登录&#xff1a; 1.1 直接登录…