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贪心#03】最大子序和
最大子序和 力扣题目链接 给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 子数组 是数组中的一个连续部分. 示例 1: 输入:nums = ...
- 【防忘笔记】一个例子理解Pytorch中一维卷积nn.Conv1d
一维卷积层的各项参数如下 torch.nn.Conv1d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1 ...
- The OCaml Language Cheatsheets
The OCaml Language Cheatsheets OCaml v.4.08.1 Syntax Implementations are in .ml files, interfaces ar ...
- BIGO 的数据管理与应用实践
本文首发于 Nebula Graph Community 公众号 本文整理自 BIGO 在 nMeetp 上的主题分享,主要介绍 BIGO 过去一年在数据管理建设方面的理解和探索.而 BIGO 数据管 ...
- Java 小练习 创建类 + 调用(1)
1 package com.bytezero.exer; 2 3 /** 4 * 5 * @Description 6 * @author Bytezero·zhenglei! Email:42049 ...
- CYQ.Data 支持 DaMeng 达梦数据库
DaMeng 达梦数据库介绍: 达梦数据库(DMDB)是中国自主研发的关系型数据库管理系统,由达梦科技股份有限公司开发. 达梦数据库提供了企业级的数据库解决方案,广泛应用于金融.电信.政府.制造等行业 ...
- MySql变量说明
1 #变量 2 /* 3 系统变量: 4 全局变量 5 会话变量 6 7 自定义变量: 8 用户变量 9 局部变量 10 11 */ 12 #一.系统变量 13 /* 14 说明:变量由系统定义,不是 ...
- 调试分析 Linux 0.00 多任务切换
当执行完 system_interrupt 函数,执行 153 行 iret 时,记录栈的变化情况. 任务0在刚进入system_interrupt函数时(调用中断int 0x80处理程序),栈空间为 ...
- br 词根 分支 broad bread branch brother broom 看到abroad后查到的
br-分支 cl-集合 pater-父亲 br/other 兄弟-br/oom笤帚-br/eed繁殖-br/ood一窝-br/eak打破-br/anch分枝 cl/ash碰撞-class/ify分类- ...
- C++ explicit 关键字简介
explicit 关键字修饰构造函数 防止类的初始化的时候进行隐式转换. class MyClass { string m_s; int m_a, m_b; public: MyClass(strin ...