Java并发编程:Java内存模型JMM
简介
Java内存模型英文叫做(Java Memory Model),简称为JMM。Java虚拟机规范试图定义一种Java内存模型来屏蔽掉各种硬件和系统的内存访问差异,实现平台无关性。
CPU和缓存一致性
讲JMM之前,我们应该先了解下CPU和缓存一致性的问题。计算机在执行程序的时候,每条指令都是在CPU中执行的,而执行的时候,又要和数据打交道。而计算机上面的数据,是存放在内存当中的。随着CPU的高速发展,从内存中读取和写入数据的过程和CPU的执行速度比起来差距就会越来越大,这导致了CPU不能满负荷的工作,需要去等待数据从内存中读取或者写入。
为了解决内存和CPU速度不一致的问题,继而引入了高速缓存这么一个东西。在CPU和内存之间,放一个高速缓存作为缓冲,这样一来就提升了CPU的读写速度。
高速缓存解决了处理器和内存速度的矛盾,但是却引入了另外一个复杂的问题——缓存一致性。在多处理器系统中,每个处理器都有自己的高速缓存,而内存又是各处理器共享的,这就可能导致各自的缓存数据不一致的情况。
为了解决缓存一致性的问题,各个处理器访问缓存时都遵循一定的协议,在读写时根据协议来操作,进而保证缓存的一致性。为了保证共享内存的正确性(可见性、有序性、原子性),内存模型定义了共享内存系统中多线程程序读写操作行为的规范。
Java内存模型(JMM)
Java虚拟机规范试图定义一种Java内存模型来屏蔽掉各种硬件和系统的内存访问差异,实现平台无关性。其底层是根据不同系统的缓存读写协议分别进行处理的。开发者不用去关心各系统的差异,因为JVM已经帮我们屏蔽了各系统的细节差异,我们只需要关注JMM即可。
Java内存模型就是一种符合内存模型规范的,屏蔽了各种硬件和操作系统的访问差异的,保证了Java程序在各种平台下对内存的访问都能保证效果一致的机制及规范。
Java内存模型定义了线程和主内存之间的抽象关系,Java各线程之间的通信是有Java内存模型所控制的。从抽象来讲,线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的工作内存(本地内存)(local memory),本地内存中存储了该线程以读 / 写共享变量的副本。
Java内存模型里所说的主内存,和工作内存(本地内存),都是抽象的概念,真实是不存在的,要区别于CPU高速缓存和内存设备。JMM只是JVM为了屏蔽系统内存操作的差异所抽象出来的概念。
主内存和工作内存(本地内存)
Java内存模型规定了所有的变量都在主内存中,每条线程都有自己的工作内存。Java线程工作的时候,从主内存load数据到自己的工作内存中,这时工作内存就持有了主内存的一份数据拷贝。线程操作完之后,把数据重新save回主内存中。
线程安全问题
理解Java内存模型,是理解线程安全问题的基础。知道JMM有主内存和工作内存之分之后,我们就很容易的理解多个线程操作同个共享变量可能引发的数据不一致的问题。假设有如下代码:
public class Main {private static int a = 0;public static void main(String[] args) throws InterruptedException {for (int i = 0; i < 10000; i++) {new Thread(() -> {a = a+1;}).start();}Thread.sleep(3000);System.out.println(a);}}
复制代码
这里有一万个线程去操作共享数据a,如果不存在并发问题的话,“预期的结果应该是10000”。执行程序,结果:
结果一:
结果二:
结果三:
实际的结果是没法预测的,理解了上面主内存和工作内存之分之后,相信你很快能理解其中的原因。假设a等于0,同时存在两个线程对其做了++操作,这时两个工作内存的a都是1,回写到主内存的时候也是1,“相当于少了一个1了”。
总结
本文介绍了Java的内存模型,这里需要强调的一点是,Java内存模型不同于Java内存结构,不要将二者概念混淆。Java内存模型是为了解决各线程之间的通信所抽象出来的概念,Java内存结构则是Java中的数据存储形式,也就是经常提到的堆内存、栈内存等。
转载于:https://juejin.im/post/5d08f7215188256b150a3620
Java并发编程:Java内存模型JMM相关推荐
- java并发编程系列-内存模型基础
java线程之间的通信对程序开发人员是完全透明的,内存的可见性问题很容易困扰很多开发人员.本篇博文将揭开java内存模型的神秘面纱,来看看内存模型到底是怎样的. 并发编程中需要处理的两个关键问题: · ...
- Java并发编程-Java内存模型(JMM)
前言 在上一章 Java并发编程-Android的UI框架为什么是单线程的? 中笔者介绍了并发编程线程安全「三大恶」:「可见性」.「原子性」以及「有序性」 广义上来说,并发编程问题笔者归纳为:是由于后 ...
- java 并发模型总类_java并发编程系列-内存模型基础
java线程之间的通信对程序开发人员是完全透明的,内存的可见性问题很容易困扰很多开发人员.本篇博文将揭开java内存模型的神秘面纱,来看看内存模型到底是怎样的. 并发编程模型的分类 并发编程中需要处理 ...
- java 并发存储,java并发编程——Java存储模型(JMM)
--仅作笔记使用,内容多摘自<java并发编程实战> Java内存模型(JMM) JMM是Java并发编程的基础,了解JMM,可以帮助我们对并发编程的机制有更深入的了解,在了解JMM之前, ...
- java并发编程-volatile内存实现和原理
2019独角兽企业重金招聘Python工程师标准>>> 前面的博文说了java的内存模型,介绍了java内存模型的基础,此篇文章来说一下volatile关键字,这个在并发编程中,占有 ...
- java并发编程(7) 共享模型之工具 - stampedLock、semaphore、CountdownLatch、CyclicBarri
文章目录 前言 1. stampedLock 1. 概述 2. 代码 1. 读读 2. 读写 3. 注意 2. Semaphore 1. 基本使用 2. 应用场景 3. 原理 3. Countdown ...
- 1. Java并发编程-Java内存模型
并发问题的原因可以归结为三大类:可见性,有序性和原子性. 可见性的原因是CPU缓存,不同CPU之间缓存的数据互相之间不可见. 有序性的原因是编译优化(指令重排序) 原子性的原因是一条高级指令可能对应多 ...
- Java并发篇_Java内存模型
在并发编程中,我们通常会遇到以下三个问题:原子性问题,可见性问题,有序性问题.那么它们产生的原因和在Java中解决的办法又是什么呢? 一.内存模型的相关概念 计算机在执行程序时,每条指令都是在CP ...
- java float内存结构_Java后端开发岗必备技能:Java并发中的内存模型
欢迎关注专栏: Java架构技术进阶 .里面有大量batj面试题集锦,还有各种技术分享,如有好文章也欢迎投稿哦. JMM通过构建一个统一的内存模型来屏蔽掉不同硬件平台和不同操作系统之间的差异,让Jav ...
- Java并发编程实战~Actor 模型
Hello Actor 模型 Actor 模型本质上是一种计算模型,基本的计算单元称为 Actor,换言之,在 Actor 模型中,所有的计算都是在 Actor 中执行的.在面向对象编程里面,一切都是 ...
最新文章
- MF0 AI+IoT K210 人脸识别模块 应用笔记-(1)
- 人工智能人才争抢白热化?学好数学才能C位出道
- [Leedcode][JAVA][第155题][最小栈][基本类型包装类]
- java 中JFinal getModel方法和数据库使用出现问题解决办法
- python 收发邮件_Python 【收发邮件】
- 一文了解Innodb中的锁
- Datagard產生gap
- Android性能优化-过度绘制解决方案
- python echarts教程_ECharts 入门教程
- css中url用法,css cursor url用法格式详解
- input输入框禁用苹果系统键盘的return键
- 深度长文:AMD的崛起、衰落与复兴
- 个人所得税税率怎么算
- win7安装解压版mysql_win7安装解压缩版mysql 5.7.19和卸载后重新安装
- Node.js项目中动态加载环境变量配置
- 使用-section等参数实现对库的裁剪,从而减小程序体积
- 生成10位由大小写字母和数字组成的随机激活码
- 关于计算重叠四边形的面积的算法
- 从拜占庭将军问题到分布式系统的一致性
- 网站服务器迁移公告,服务器地址迁移通知怎么写