java内存模型(jmm)概念初探
1.和java内存结构的区别:
很多人会把jmm和Java内存结构搞混,网上搜到的一些文章也是如此,java内存结构就是我们常说的堆,栈,方法区,程序计数器..., 当jvm虚拟机启动的时候,会初始化这些内存区域。而java内存模型是一套虚拟机规范,它遵循虚拟机规范定义了一套用于处理多线程下对数据的原子性,可见性,有序性的规则,它在每个jvm下的实现都可以是不同的,只要符合虚拟机规范就可以。
要知道java内存模型设计的意义,首先我们可以了解一下操作系统的内存模型:
2.操作系统内存模型
在最早的时候,cpu和内存直接打交道,那个时候两者速度是差不多的,但是后来随着cpu发展迅速,内存速度越来越跟不上了,cpu每次获取数据的时候就干瞪眼,于是乎就出现了高速缓存,寄存器这些玩意,但是这玩意是每个核心独有的,你其他核心访问的时候还是从你自己的寄存器-几级高速缓存-主存获取,主存是共享的,但是你总不能每次改一下,就刷一次主存,那也太慢了,没啥意义,所以你肯定得攒一段时间再写到主存,于是乎,一个共享的变量,你改了,但是还没到你要刷到主存的时候,我也改了,但是我读不到你缓存里的数据,那肯定就会出现缓存不一致的问题。
除了这种情况,cpu为了让内部的运算单元能被充分利用,可能会打乱代码顺序执行,我们听过的指令重排就是java虚拟机层面类似的优化,那么这种问题如何能解决呢其实这些就是我们所说的原子性,可见性,顺序性发生的原因,那么操作系统层面是怎么保证的呢,我总不能为了速度,不管他对不对了吧。为了解决数据一致性的问题,通常各个处理器访问缓存都遵循一些协议,主要有:MSI、MESI(Illinois Protocol)、MOSI、Synapse、Firefly 及 Dragon Protocol 等,下面我们主要介绍一下MESI:
3.MESI
在多核处理器中,缓存都是独立的,但是多核之间需要共享数据,那么我们如何保证这些数据的一致性?
在MESI中,每个缓存行都有4中状态:M ,E, S,I
M: M全称Modified,它标识这行数据在本缓存被修改了,和内存中不一致,但本缓存是有效的,如果别的CPU内核要访问主存中这块数据,则该缓存行数据必须先写回主存,状态改为S
E: 全称Exclusive,表示当前数据有效,但数据只有该缓存和主存有,当别的Cpu读时,状态改为S,如果被修改了,改为M
S: 全称Shared,表示当前缓存行在其他缓存中也有,且自身未修改,缓存行可以被抛弃(缓存行有自己的淘汰策略)
I: 全称invalid,表示当前缓存行是无效的。
基于上面的知识,其实可以大致知道MESI就是通过在读写数据时,通知所有拥有这块数据的核心修改自身的状态,达到在任意时刻任意核心读到的数据都是一致的,而且不需要实时更新数据到主存或其他缓存。
java内存模型和操作系统的是比较类似的,它的所有操作基本上都是对底层的映射,它定义了线程和主存之间的抽象的映射关系:
线程间共享的变量存在主存中,线程的独有的缓存存储变量的副本,其实大体上和操作系统理解起来是一个道理。
jmm是比较抽象的一个概念,必须要结合操作系统的内存模型来结合理解,像操作系统为了提升性能,加了多级缓存,加了寄存器,并且会优化要执行的代码。而加了之后也是有代价的,那就是会造成所谓的并发三大特性:
1.可见性:就是当一个共享变量被其他线程修改后,当前线程可以立刻读到改变后的值。
为什么会出现可见性问题?
如上图所示,每个线程都有自己的本地缓存(为了效率),而本地缓存就会导致如线程2将一个共享变量变更了,刷到主存中,但线程1不知道我这个值变了,还是会去读缓存,就会导致线程2的修改对线程1不可见。
如何解决可见性问题:
1.volatile关键字
2.通过直接调用内存屏障storeFence()
3.synchronized关键字
4.Lock保证
5.final关键字
2.有序性:
用一句通俗但又不易懂的话来说就是眼见不一定为实,怎么理解呢,jvm为了效率,有时候会对指令进行重排,它不一定会按照你写的代码一步步执行,当然有前后依赖关系的肯定不会重排。
如何解决有序性问题:
1.volatile关键字
2.通过直接调用内存屏障storeFence()
3.synchronized关键字
4.Lock保证
3.原子性:
要么都执行,要么不执行,不管你有多少个线程同时执行,我这个原子性的操作一定是不会被打断或者拆分执行,相当于是这个操作以及不能再被拆分了。
如何保证原子性:
1.CAS的方式
2.synchronized关键字
3.Lock保证
本章节主要介绍了操作系统内存模型的设计,延伸到jmm的设计,以及这样的设计带来的影响,操作系统会通过实现一些一致性协议来解决这样的问题,java则通过上述一些方式来处理三大特性的问题,后续章节将介绍这些方式解决三大特性的原理。
.tb_button { padding: 1px; cursor: pointer; border-right: 1px solid rgba(139, 139, 139, 1); border-left: 1px solid rgba(255, 255, 255, 1); border-bottom: 1px solid rgba(255, 255, 255, 1) }
.tb_button.hover { borer: 2px outset #def; background-color: rgba(248, 248, 248, 1) !important }
.ws_toolbar { z-index: 100000 }
.ws_toolbar .ws_tb_btn { cursor: pointer; border: 1px solid rgba(85, 85, 85, 1); padding: 3px }
.tb_highlight { background-color: rgba(255, 255, 0, 1) }
.tb_hide { visibility: hidden }
.ws_toolbar img { padding: 2px; margin: 0 }
.tb_button { padding: 1px; cursor: pointer; border-right: 1px solid rgba(139, 139, 139, 1); border-left: 1px solid rgba(255, 255, 255, 1); border-bottom: 1px solid rgba(255, 255, 255, 1) }
.tb_button.hover { borer: 2px outset #def; background-color: rgba(248, 248, 248, 1) !important }
.ws_toolbar { z-index: 100000 }
.ws_toolbar .ws_tb_btn { cursor: pointer; border: 1px solid rgba(85, 85, 85, 1); padding: 3px }
.tb_highlight { background-color: rgba(255, 255, 0, 1) }
.tb_hide { visibility: hidden }
.ws_toolbar img { padding: 2px; margin: 0 }
.tb_button { padding: 1px; cursor: pointer; border-right: 1px solid rgba(139, 139, 139, 1); border-left: 1px solid rgba(255, 255, 255, 1); border-bottom: 1px solid rgba(255, 255, 255, 1) }
.tb_button.hover { borer: 2px outset #def; background-color: rgba(248, 248, 248, 1) !important }
.ws_toolbar { z-index: 100000 }
.ws_toolbar .ws_tb_btn { cursor: pointer; border: 1px solid rgba(85, 85, 85, 1); padding: 3px }
.tb_highlight { background-color: rgba(255, 255, 0, 1) }
.tb_hide { visibility: hidden }
.ws_toolbar img { padding: 2px; margin: 0 }
java内存模型(jmm)概念初探的更多相关文章
- Java内存模型JMM与可见性
Java内存模型JMM与可见性 标签(空格分隔): java 1 何为JMM JMM:通俗地讲,就是描述Java中各种变量(线程共享变量)的访问规则,以及在JVM中将变量存储到内存和从内存中读取变量这 ...
- 多线程并发之java内存模型JMM
多线程概念的引入是人类又一次有效压寨计算机的体现,而且这也是非常有必要的,因为一般运算过程中涉及到数据的读取,例如从磁盘.其他系统.数据库等,CPU的运算速度与数据读取速度有一个严重的不平衡,期间如果 ...
- Java内存模型JMM 高并发原子性可见性有序性简介 多线程中篇(十)
JVM运行时内存结构回顾 在JVM相关的介绍中,有说到JAVA运行时的内存结构,简单回顾下 整体结构如下图所示,大致分为五大块 而对于方法区中的数据,是属于所有线程共享的数据结构 而对于虚拟机栈中数据 ...
- 全面理解Java内存模型(JMM)及volatile关键字(转载)
关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解Java类加载器(ClassLoad ...
- 全面理解Java内存模型(JMM)及volatile关键字(转)
原文地址:全面理解Java内存模型(JMM)及volatile关键字 关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型( ...
- 对多线程java内存模型JMM
多线程概念的引入体现了人类重新有效压力寨计算机.这是非常有必要的,由于所涉及的读数据的过程中的一般操作,如从磁盘.其他系统.数据库等,CPU计算速度和数据读取速度已经严重失衡.假设印刷过程中一个线程将 ...
- Java内存模型(JMM)详解
在Java JVM系列文章中有朋友问为什么要JVM,Java虚拟机不是已经帮我们处理好了么?同样,学习Java内存模型也有同样的问题,为什么要学习Java内存模型.它们的答案是一致的:能够让我们更好的 ...
- Java并发编程:Java内存模型JMM
简介 Java内存模型英文叫做(Java Memory Model),简称为JMM.Java虚拟机规范试图定义一种Java内存模型来屏蔽掉各种硬件和系统的内存访问差异,实现平台无关性. CPU和缓存一 ...
- 深入理解Java内存模型JMM
本文转载自深入理解Java内存模型JMM JMM基础与happens-before 并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执 ...
- 什么是Java内存模型(JMM)
什么是java内存模型 缓存一致性问题 在现代计算机中,因为CPU的运算速度远大于内存的读写速度,因此为了不让CPU在计算的时候因为实时读取内存数据而影响运算速度,CPU会加入一层缓存,在运算之前缓存 ...
随机推荐
- 【LeetCode贪心#04】跳跃游戏I + II
跳跃游戏 力扣题目链接(opens new window) 给定一个非负整数数组,你最初位于数组的第一个位置. 数组中的每个元素代表你在该位置可以跳跃的最大长度. 判断你是否能够到达最后一个位置. 示 ...
- 简单配置Sql专家云
一.实例配置 1.添加实例 点击全面诊断实例配置,右上角点击添加. 2.填写实例信息 根据下图填写对应的信息,连接测试成功后点击保存. 3.添加完成 4.修改实例 找到对应的实例,点击下图蓝色框修改即 ...
- 开源:Taurus.Idempotent 分布式幂等性锁框架,支持 .Net 和 .Net Core 双系列版本
分布式幂等性锁介绍: 分布式幂等性框架的作用是确保在分布式系统中的操作具有幂等性,即无论操作被重复执行多少次,最终的结果都是一致的.幂等性是指对同一操作的多次执行所产生的效果与仅执行一次的效果相同. ...
- Python函数对象与闭包函数
[一]函数对象 函数对象指的是函数可以被当做 数据 来处理,具体可以分为四个方面的使用 [1]函数可以被引用 def add(x,y): return x + y func = add res = f ...
- 基于RocketMQ实现分布式事务
背景 在一个微服务架构的项目中,一个业务操作可能涉及到多个服务,这些服务往往是独立部署,构成一个个独立的系统.这种分布式的系统架构往往面临着分布式事务的问题.为了保证系统数据的一致性,我们需要确保这些 ...
- rst文件查看(Sphinx)
reStructuredText ( RST . ReST 或 reST )是一种用于文本数据的文件格式,主要用于 Python 编程语言社区的技术文档. 在下载了别人的Python源文件里面有rst ...
- 4时4态 加被动 例句:I will have been being done - will have be be do - 频率副词位置
4时4态 频率副词的用法和位置:放在实义动词之前.放在be 动词之后.放在情态动词之后. 频率副词的位置一般是放在实义动词之前.放在be 动词之后.放在情态动词之后.放在be动词之后:She is s ...
- Springboot K8s Job 一次性任务 如何禁用端口监听
问题:SpringBoot一次性任务执行时,也会默认监听服务端口,当使用k8s job运行时,可能多个pod执行存在端口冲突 解决办法:命令行禁用SpringBoot一次性任务启动时端口占用 java ...
- Rust 标准库 Trait 指南
部分内容来自 Rust 2021 年期刊 内容目录 引言 Trait 基础 自动 Trait 泛型 Trait 格式化 Trait 操作符 Trait 转换 Trait 错误处理 迭代器 Trait ...
- electron程序运行在某些 windows 上白屏
现象: 打包后的 electron 程序 运行在某些 windows 上白屏 项目情况: vue3.0 项目使用 vue-cli 创建 使用 vue add electron-builder 添加打 ...