简单了解JMM

什么是JMM

对于不同的硬件和操作系统,有着自己的底层内存模型,可能导致Java程序在一些的平台可以正确并发,而在另一些平台出现并发错误,JMM是Java内存模型,是语言级别的内存模型,用于屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的并发效果,JMM主要考虑的就是各种变量的访问规则,正确实现线程间的通信以及线程间的同步,对于JMM,把各种硬件抽象为本地内存和主存来存放变量。

总的来说JMM把硬件和操作系统的差异屏蔽了,让Java在不同机器上都可以正确的实现并发。

image-20240318203150822

内存间交互操作

关于变量如何从主存拷贝到本地线程以及变量如何从本地线程同步到主存的细节,JMM定义了8中操作来完成,对于每个线程来说,只能操作本地内存的变量,规定read、load要顺序执行,store、write要顺序执行。

image-20240318205713894

操作系统的三大问题

在谈论JMM之前,首先我们需要了解操作系统的几个问题,JMM正是解决了操作系统这些问题。

随着时代的发展,计算机逐步更新换代,人们对于计算机的要求越来越高,对于家庭或者公司的电脑需要人机交互,这就要求计算机需要有较短的响应时间,为此工程师引入了CPU的多级缓存、时间片轮转调度算法、指令优化重排,但是也相应的带来了问题:

  • CPU缓存一致性问题(可见性),解决方案:总线锁、MESI协议

  • 代码被多个线程访问的并发问题(原子性),解决方案:锁

  • 指令没有按照程序员的意愿执行(有序性)

JMM抽象的问题

可见性:线程本地变量和内存的可见性问题,规定线程只能操作本地内存变量,线程对内存的修改无法及时被其它线程看到

原子性:如 i++ 语句,底层由多条指令组成,CPU实际执行的是指令,在指令执行期间可能会发生时钟中断切换线程,最终导致程序执行结果出问题

有序性:如 Java 创建对象过程,类加载 -> 实例化 -> 初始化 -> 引用赋值,由于指令重排可能导致引用赋值在初始化之前,导致其它线程使用到未初始化的对象

Java关键字如何解决问题

  • 可见性:

    • 可通过volatile关键字解决,强制线程每次修改本地变量需要同步到主存,同时每次读取本地变量都需要从主存读取

    • 可通过synchrinized关键字解决:锁获取和volatile读有相同的语义,将本地变量置为无效状态,锁释放和volatile写有相同的语义,变量需要同步到主存

    • 可通过final关键字解决

  • 原子性:可通过synchrinized关键字解决,底层是通过monitorenter和monitorexit字节码指令

  • 有序性:

    • 可通过volatile关键字解决,volatile规则

    • 可通过synchrinized关键字解决,程序次序规则(只有一个线程访问同步代码块,单线程重排优化语义是一样的)

Happens-Before原则

如果JMM中所有的有序性仅靠volatile和synchronized来完成,未免很多操作有点啰嗦,我们在日常编码的过程中并不会过多关注有序性,因为有个Happens-Before原则来辅助保证代码操作的顺序性

常见的Happens-Before原则:

  • 程序次序规则:同一个线程内,对于顺序执行,前面的操作先行于后面的操作

  • 管程锁定规则:对于一个锁,unlock先行于lock

  • volatile规则:对于一个用volatile修饰的变量,写操作先行于读操作

  • 线程启动规则:start()先行于这个线程的其它动作

  • 线程终止规则:线程所有动作先行于终止检查

  • 线程中断规则:interrupt()先行于检测到中断事件的发生

  • 对象终止规则:对象的初始化完成先行于销毁

  • 传递性:A操作先行于B操作,B操作先行于C操作,那么A操作先行于C操作

如下面这个程序,你不能保证 i = 1 一定会在 j = 2 前执行,但是这也不影响Happens-Before原则的正确性,因为这并不影响整个程序执行结果的正确性。

 int i = 1;
 int j = 2;

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

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

相关文章

Activiti7学习大纲及环境-Activiti7从入门到专家(2)

学习大纲 入门系列 开发环境及源码编译流程设计器核心API简单流程示例启动与结束事件边界事件中间事件用户任务手动任务接受任务服务任务脚本任务业务规则任务排他网关并行网关包容网关事件网关子流程调用活动泳池泳道执行监听器任务监听器全局监听器真实业务流程 进阶系列 …

蓝桥杯真题讲解:网络稳定性(Kruskal重构树+LCA)

蓝桥杯真题讲解&#xff1a;网络稳定性&#xff08;Kruskal重构树LCA&#xff09; 一、视频讲解二、正解代码 一、视频讲解 蓝桥杯真题讲解&#xff1a;网络稳定性&#xff08;Kruskal重构树LCA&#xff09; 二、正解代码 //kruskal重构树 lca #include<bits/stdc.h>…

lora-scripts 训练IP形象

CodeWithGPU | 能复现才是好算法CodeWithGPU | GitHub AI算法复现社区&#xff0c;能复现才是好算法https://www.codewithgpu.com/i/Akegarasu/lora-scripts/lora-trainstable-diffusion打造自己的lora模型&#xff08;使用lora-scripts&#xff09;-CSDN博客文章浏览阅读1.1k次…

Springboot+vue的高校实习管理系统(有报告)。Javaee项目,springboot vue前后端分离项目。

演示视频&#xff1a; Springbootvue的高校实习管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09…

YOLOV8环境配置精简

AnacondaCUDA_cuDNN的安装这里就不详细介绍了&#xff0c;按照网上的教程基本可用&#xff0c;但是我的难题主要集中在Pycharm新建conda虚拟环境和Yolov8的工程验证上&#xff0c;所以本文记录自己解决问题的过程。 一&#xff0c;Ultralytics官网下载Yolov8源码&#xff0c;解…

stable diffusion 提示词进阶语法-年龄身材肤色-学习小结

stable diffusion 提示词进阶语法-年龄&身材&肤色 前言年龄提示词青年&#xff08;18-25岁&#xff09;幼年、少年&#xff08;1-18&#xff09;中年&#xff08;35-60岁&#xff09;老年&#xff08;65-80岁 老爷爷 老奶奶&#xff09; 身材提示词肤色关键词(人物基础…

Flink中JobManager与TaskManage的运行架构以及原理详解

Flink中JobManager与TaskManage的运行架构详解 整体架构 Flink的运行时架构中&#xff0c;最重要的就是两大组件&#xff1a;作业管理器&#xff08;JobManger&#xff09;和任务管理器&#xff08;TaskManager&#xff09;。对于一个提交执行的作业&#xff0c;JobManager是真…

Flume超级无敌详细讲解

简介 概述 Flume本身是由Cloudera公司开发的后来贡献给了Apache的一套针对日志进行收集(collecting)、汇聚(aggregating)和传输(moving)的分布式机制。 图-1 Flume图标 Flume本身提供了较为简易的流式结构,使得开发者能够较为简易和方便的搭建Flume的流动模型。 图-2 Flume…

【管理咨询宝藏56】大型德企业务战略规划报告

本报告首发于公号“管理咨询宝藏”&#xff0c;如需阅读完整版报告内容&#xff0c;请查阅公号“管理咨询宝藏”。 【管理咨询宝藏56】大型德企业务战略规划报告 【格式】PDF 【关键词】战略规划、商业分析、管理咨询 【核心观点】 - 这是一份非常完整的知名德企在华业务战略…

c++ 三元搜索 - 迭代与递归(Ternary Search)

计算机系统使用不同的方法来查找特定数据。有多种搜索算法&#xff0c;每种算法更适合特定情况。例如&#xff0c;二分搜索将信息分为两部分&#xff0c;而三元搜索则执行相同的操作&#xff0c;但分为三个相等的部分。值得注意的是&#xff0c;三元搜索仅对排序数据有效。在本…

数据分析案例-国际象棋顶级棋手数据可视化分析(文末送书)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

Spring异步注解@Async线程池配置

系列文章目录 文章目录 系列文章目录前言前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 从Spring3开始提供了@Async注解,该注解可以被标注在方法上,以便异步地调…

mysql字段多个值,mybatis/mybatis-plus匹配查询

mysql中有一个字段是字符串类型的&#xff0c;category字段值有多个用逗号分割的&#xff0c;例如&#xff1a;娱乐,时尚美妆,美食 。现在想实现这么一个功能&#xff0c; 前端传参 字符串&#xff0c;美食,娱乐。现在想在mybatis的xml中实现&#xff0c;查询&#xff0c;能查到…

Linux基础语法练习题,配有答案,题目内容如下:一、创建文件相关练习题二、文件管理相关练习题三、vim编辑器的练习四、用户管理相关操作

题目内容如下&#xff1a; 一、创建文件相关练习题 二、文件管理相关练习题 三、vim编辑器的练习 四、用户管理相关操作 一、创建文件相关练习题 1.进入根目录&#xff0c;列出当前目录的详细信息 2、在根目录下创建export目录 3.进入export目录&#xff0c;创建data目录 …

基于python+vue反诈科普平台的设计与实现flask-django-php-nodejs

课题主要采用Uni-weixin、django架构技术&#xff0c;前端以小程序页面呈现给用户&#xff0c;结合后台python语言使页面更加完善&#xff0c;后台使用MySQL数据库进行数据存储。微信小程序主要包括用户信息、反诈科普、一键举报、经历上传、交流论坛、科普测试、试题等功能&am…

嵌入式DSP教学实验箱操作教程:2-20 数模转换实验(模拟SPI总线输出电压值)

一、实验目的 掌握GPIO模拟SPI总线的使用&#xff0c;了解AD5724的芯片特性和使用&#xff0c;并实现基于AD5724输出电压值。 二、实验原理 StarterWare StarterWare是一个免费的软件开发包&#xff0c;它包含了示例应用程序。StarterWare提供了一套完整的GPIO寄存器配置接…

详细分析Python中的enumerate()函数(附多个Demo)

目录 前言1. 基本知识2. Demo 前言 对于Python的基本函数&#xff0c;从实战中获取确切知识 1. 基本知识 enumerate() 接受一个可迭代对象作为输入&#xff0c;并返回一个枚举对象这个枚举对象包含了原始可迭代对象中的每个元素以及对应的索引它允许在循环中同时获取索引和值…

linux系统------------MySQL 存储引擎

目录 一、存储引擎概念介绍 二、常用的存储引擎 2.1MyISAM 2.1.1MYlSAM的特点 2.1.2MyISAM 表支持 3 种不同的存储格式⭐&#xff1a; &#xff08;1&#xff09;静态(固定长度)表 &#xff08;2&#xff09;动态表 &#xff08;3&#xff09;压缩表 2.1.3MyISAM适…

Golang基础知识(笔记迁移)

golang 变量作用域 局部作用域&#xff1a;代码块、函数内的全局作用域&#xff1a;顶层作用域&#xff0c;代码块外的就是全局&#xff0c;如果变量名大写&#xff0c;则改变量整个程序都可以使用。 类型断言 golang的类型断言在变量后加上.(type)&#xff0c;如果类型断言…

Java面试必问题16:HashMap和HashTable区别 ConcurrentHashMap和HashMap的区别

HashMap和HashTable区别 ConcurrentHashMap和HashMap是Java中常用的两种Map实现&#xff0c;它们之间有以下几个区别&#xff1a; 线程安全性&#xff1a;ConcurrentHashMap是线程安全的&#xff0c;多个线程可以同时对其进行读写操作而不需要额外的同步措施&#xff1b;而Has…