文档章节

带你了解 Java内存模型

l
 linux-tao
发布于 2019/10/17 09:11
字数 1214
阅读 80
收藏 0

Java内存模型的规定:

1、所有变量存储在主内存中;

2、每个线程都有自己的工作内存,且对变量的操作都是在工作内存中进行;

3、不同线程之间无法直接访问彼此工作内存中的变量,要想访问只能通过主内存来传递。

Java的线程、工作内存、主内存关系如下图所示:

具体变量从主内存到工作内存,以及从工作内存转回主内存的实现细节,由下面八个原子性的操作完成:

lock:作用于主内存变量,将该变量标识为一个线程独占的状态

unlock:作用于主内存变量,将独占状态释放

read:作用于主内存变量,将值拷贝到工作内存中

load:作用于工作内存中的变量,将值放到工作内存中的变量副本中

use:作用于工作内存中的变量,将值传给执行引擎

asign:作用于工作内存中的变量,将执行引擎中的值赋给工作内存中的变量

store:作用于工作内存中的变量,将值传给主内存

write:作用于主内存中的变量,将工作内存中返回的值放到主内存变量中

同时还对上述八个操作进行了一些细节的要求,比如read/load、store/write必须成对出现,未执行过lock的变量不能执行unlock操作等。

划重点,此处面试常遇到的问题就是对于volatile关键字的解读。

volatile关键字

此关键字修饰的变量具有两种效果:1、保证线程间的可见性;2、阻止指令重排序

对于1的实现,它保证load与use必须相邻调用,即要use这个变量,必定先执行read/load,这样每次都能获取到最新的变量值;它又保证asign与store必须相邻调用,即在工作内存中将该变量改了之后,必定会先同步到主内存中。这样,volatile关键字实现了可见性。至于阻止指令重排序,还是移步《深入理解Java虚拟机》一书吧,贫道水平有限,就不在这里说了。

从另一个角度来分析,Java内存模型是围绕着在并发过程中如何处理原子性、可见性、有序性来建立的。

原子性:八个原子性操作,以及synchronized(lock/unlock未直接开放给用户,synchronized通过monitorenter跟monitorexit指令调用的lock/unlock操作)

可见性:volatile、synchronized、final这三个关键字均通过不同方式实现了可见性

有序性:volatile、synchronized 这两个关键字保证有序性,同时还有先行发生(happens-before)原则来保证隐含的默认有序性

下面说说happens-before先行发生原则,先行发生原则用通俗语言表述就是:如果操作A在操作B之前发生,那么A产生的影响B同样能观测到。那么问题来了,先行发生原则都有哪些呢?同样有八条,如下:

程序次序规则:同一个线程中按照代码的顺序依次执行

管程锁定规则:对于同一个锁,unlock先行发生于后面的lock,即unlock了才会lock

volatile变量规则:对一个volatile变量的写操作先行发生于后面对该变量的读操作,即写完了才会读

线程启动规则:一个线程的start()方法先行发生于此线程的任何一个动作

线程终止规则:一个线程的所有动作先行发生于该线程的终止检测

线程中断规则:对一个线程interrupt()方法的调用先行发生于线程的中断检测Thread.interrpted()

对象终结规则:对象的初始化完成先行发生于finalize()方法

传递性:顾名思义,A先行发生于B,B先行发生于C,则A一定先行发生于C

总结

Java内存模型基本就这些内容,如果都掌握了的话,非一线互联网公司基本都能应对自如了(因为一线互联网公司贫道本人也没进去><)。

原文来自:https://www.linuxidc.com/Linux/2019-08/160335.htm

本文地址:https://www.linuxprobe.com/read-java-load.html编辑:九十,审核员:张文祥

Linux命令大全:https://www.linuxcool.com/

© 著作权归作者所有

l
粉丝 21
博文 1008
码字总数 1130720
作品 0
深圳
运维
私信 提问
加载中

评论(0)

求你了,再问你Java内存模型的时候别再给我讲堆栈方法区了…

GitHub 4.1k Star 的Java工程师成神之路 ,不来了解一下吗? GitHub 4.1k Star 的Java工程师成神之路 ,真的不来了解一下吗? GitHub 4.1k Star 的Java工程师成神之路 ,真的确定不来了解一下吗...

Hollis
2019/07/02
0
0
区分 JVM 内存结构、 Java 内存模型 以及 Java 对象模型 三个概念

本文由 简悦 SimpRead 转码, 原文地址 https://www.toutiao.com/i6732361325244056072/ Java 作为一种面向对象的,跨平台语言,其对象、内存等一直是比较难的知识点。而且很多概念的名称看起...

王代军
2019/09/04
0
0
基于JVM原理、JMM模型和CPU缓存模型深入理解Java并发编程

许多以Java多线程开发为主题的技术书籍,都会把对Java虚拟机和Java内存模型的讲解,作为讲授Java并发编程开发的主要内容,有的还深入到计算机系统的内存、CPU、缓存等予以说明。实际上,在实...

leoliu168
2018/11/08
0
0
好程序员Java教程分享之jvm篇

好程序员java教程分享之jvm篇,在前面的文章中,介绍了JVM内存模型分为:堆区、虚拟机栈、方法区、本地方法区和程序计数器,其中堆区是JVM中最大的一块内存区域,在Java中的所有对象实例都保...

好程序员IT
2019/06/11
59
0
原创 |我是如何解决POI解析Excel出现的OOM问题的?

背景 之前接手过一个解析Excel的项目,使用的是Java里的POI组件解析的,但是在解析时候经常出现OOM,后来我从下面几个方面优化了下,解决了99%的问题,对,你没看错,只解决了99%。 解决方案...

Java碎碎念
03/17
0
0

没有更多内容

加载失败,请刷新页面

加载更多

数组foreach()遍历中的传递引用

在PHP的foreach ($arr as $k => $v) 的遍历中,每一轮的遍历,都发生了以下事情 $k = currentKey($arrCopy); //将副本数组本轮次的键的值分配给$k,比如下标0,1,2等;$v = currentVal($arrCo...

vinci321
今天
140
0
将文件从Docker容器复制到主机 - Copying files from Docker container to host

问题: I'm thinking of using Docker to build my dependencies on a Continuous Integration (CI) server, so that I don't have to install all the runtimes and libraries on the agent......

技术盛宴
今天
117
0
略谈分布式系统中的容器设计模式

本文作者:zytan_cocoa 略谈分布式系统中的容器设计模式 谭中意 2020/3/5 前言:云原生(Cloud Native)不仅仅是趋势,更是现在进行时,它是构建现代的,可弹性伸缩的,快速迭代的计算网络服...

百度开发者中心
03/11
138
0
elasticsearch 第三讲

es的详细介绍 SearchTemplate tmdb 表示的是模板名称 dmdb1 表示的是当前的索引 脚本方式编辑 ##编辑模板POST _scripts/tmdb{ "script": { "lang": "mustache", "source": { ......

鸡蛋炒馒头
今天
215
0
IDEA新建springMVC项目,启动后访问Controller报404

IDEA新建springMVC项目,启动后可以访问到默认的index.jsp,但是访问controller就报404 查看web.xml配置 spingmvc.xml配置 都没有问题 请求的url也和定义的@RequestMapping一致。也没有问题。...

vicky_dimi
今天
316
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部