理解java虚拟机工作后了解吗_JAVA入门到再次入门——深入理解JAVA虚拟机(二)|七日打卡...

前言

为什么叫做入门到到再次入门请参考前一篇或个人博客,在此不再赘述,嗯哼,了解了JVM的基本运行流程以及内存结构,算是初步认识了JVM,跟着课本往前走,继续了解根据JVM的内存模型探索java当中变量的可见性以及不同的java指令在并发时可能发生的指令重排序的情况。

内存模型

首先我们思考一下一个java线程要向另外一个线程进行通信,应该怎么做,我们再把需求明确一点,一个java线程对一个变量的更新怎么通知到另外一个线程呢?我们知道java当中的实例对象、数组元素都放在java堆中,java堆是线程共享的。(我们这里把java堆称为主内存),而每一个线程都是自己私有的内存空间(称为工作内存),如果线程1要向线程2通信,一定会经过类似的流程:

dba09c88e7dcfda553525421b7aaf47d.png

1、 线程1将自己工作内存中的X更新为1并刷新到主内存中;

2、 线程2从主内存读取变量X=1,更新到自己的工作内存中,从而线程2读取的X就是线程1更新后的值。

从上面的流程看出线程之间的通信都需要经过主内存,而主内存与工作内存的交互,则需要Java内存模型(JMM)来管理器。下图演示了JMM如何管理主内存和工作内存:

4fafeaf525c6c1a0d736ff1b70305bcd.png

当线程1需要将一个更新后的变量值刷新到主内存中时,需要经过两个步骤:

1、 工作内存执行store操作;

2、 主内存执行write操作;

完成这两步即可将工作内存中的变量值刷新到主内存,即线程1工作内存和主内存的变量值保持一致;

当线程2需要从主内存中读取变量的最新值时,同样需要经过两个步骤:

1、主内存执行read操作,将变量值从主内存中读取出来;

2、工作内存执行load操作,将读取出来的变量值更新到本地内存的副本;

完成这两步,线程2的变量和主内存的变量值就保持一致了。

可见性

Java中有一个关键字volatile,它有什么用呢?这个答案其实就在上述java线程间通信机制中,我们想象一下,由于工作内存这个中间层的出现,线程1和线程2必然存在延迟的问题,例如线程1在工作内存中更新了变量,但还没刷新到主内存,而此时线程2获取到的变量值就是未更新的变量值,又或者线程1成功将变量更新到主内存,但线程2依然使用自己工作内存中的变量值,同样会出问题。不管出现哪种情况都可能导致线程间的通信不能达到预期的目的。例如以下例子:

//线程1

boolean stop = false;

while(!stop){

doSomething();

}

//线程2

stop = true;

复制代码

这个经典的例子表示线程2通过修改stop的值,控制线程1中断,但在真实环境中可能会出现意想不到的结果,线程2在执行之后,线程1并没有立刻中断甚至一直不会中断。出现这种现象的原因就是线程2对线程1的变量更新无法第一时间获取到。

但这一切等到Volatile出现后,再也不是问题,Volatile保证两件事:

1、 线程1工作内存中的变量更新会强制立即写入到主内存;

2、 线程2工作内存中的变量会强制立即失效,这使得线程2必须去主内存中获取最新的变量值。

所以这就理解了Volatile保证了变量的可见性,因为线程1对变量的修改能第一时间让线程2可见。

指令重排序

关于指令排序我们先看一段代码:

int a = 0; boolean flag = false;

//线程1

public void writer() {

a = 1;

flag = true;

}

//线程2

public void reader() {

if (flag) {

int i= a+1;

}

}

复制代码

线程1依次执行a=1,flag=true;线程2判断到flag==true后,设置i=a+1,根据代码语义,我们可能会推断此时i的值等于2,因为线程2在判断flag==true时,线程1已经执行了a=1;所以i的值等于a+1=1+1=2;但真实情况却不一定如此,引起这个问题的原因是线程1内部的两条语句a=1;flag=true;可能被重新排序执行,如图:

432e1c3777749d73012083d54beb010a.png

这就是指令重排序的简单演示,两个赋值语句尽管他们的代码顺序是一前一后,但真正执行时却不一定按照代码顺序执行。你可能会说,有这个指令重排序那不是乱套了吗?我写的程序都不按我的代码流程走,这怎么玩?这个你可以放心,你的程序不会乱套,因为java和CPU、内存之间都有一套严格的指令重排序规则,哪些可以重排,哪些不能重排都有规矩的。下列流程演示了一个java程序从编译到执行会经历哪些重排序:

cc8bcd1f5debd6c7f92a0f3945747d54.png

在这个流程中第一步属于编译器重排查,编译器重排序会按JMM的规范严格进行,换言之编译器重排序一般不会对程序的正确逻辑造成影响。第二、三步属于处理器重排序,处理器重排序JMM就不好管了,怎么办呢?它会要求java编译器在生成指令时加入内存屏障,内存屏障是什么?你可以理解为一个不透风的保护罩,把不能重排序的java指令保护起来,那么处理器在遇到内存屏障保护的指令时就不会对它进行重排序了。关于在哪些地方该加入内存屏障,内存屏障有哪些种类,各有什么作用,这些知识点这里就不再阐述了。可以参考JVM规范相关资料。

下面介绍一下在同一个线程中,不会被重排序的逻辑:

279b40e3a42142260f204ab34ff48fd9.png

这三种情况中,任意改变一个代码的顺序,结果都会大不相同,对于这样的逻辑代码,是不会被重排序的。注意这是指单线程中不会被重排序,如果在多线程环境下,还是会产生逻辑问题,例如我们一开始举的例子。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java访问错误404_如何解决 Java web 项目中的 404 错误

在使用 Tomcat 进行 Java Web 开发的时候,经常会遇到以下 HTTP 404 错误:错误代码为 HTTP 404(未找到),描述信息是:“The origin server did not find a current representation for the target resource or is not willing to di…

java double 的精度_Java Double的精度问题

Java.text类 DecimalFormatjava.lang.Objectjava.text.Formatjava.text.NumberFormatjava.text.DecimalFormatvoid setMaximumFractionDigits(int newValue) 设置某个数的小数部分中所允许的最大数字位数。void setMinimumFractionDigits(int newValue) …

java餐饮管理系统图片,基于jsp的酒店餐饮管理系统-JavaEE实现酒店餐饮管理系统 - java项目源码...

基于jspservletpojomysql实现一个javaee/javaweb的酒店餐饮管理系统, 该项目可用各类java课程设计大作业中, 酒店餐饮管理系统的系统架构分为前后台两部分, 最终实现在线上进行酒店餐饮管理系统各项功能,实现了诸如用户管理, 登录注册, 权限管理等功能, 并实现对各类酒店餐饮管…

php 验证码一直不对,ThinkPHP验证码老是出错怎么办

ThinkPHP验证码老是出错的解决办法:1、找到服务器php配置文件php.ini在网站根目录下建一个info.php文件。例如:D:\wwwRoot\wp 这个是网站的根目录,在此目录下,新建一个txt文档,输入如下代码:然后另存为info…

小皮面板有php环境吗,体验phpStudy小皮面板创建LAMP/LNMP系统和建站图文

在国庆节后老 左有看到原phpStudy面板新的Linux面板系统更新发布取名小皮面板(phpStudy Linux系统初次体验 – 一键安装phpStudy面板查看功能),初次体验这款面板之后我们肯定会会当前比较热门的宝塔面板作为比较,有些人说UI和功能上有所参考,…

php 断点续传 暂停,PHP 断点续传实例详解

在做一个案例,要给客户端做断点续传的服务,断点续传主要是HTTP协议中的Content-Range报头。其理解如下:Content-Range:响应资源的范围。可以在多次请求中标记请求的资源范围,在连接断开重新连接时,客户端只…

如何在php中插入数据并修改,php怎么同时向2张表里插入数据

情况是这个样子的:我要做一个发消息的表,因为接受人可能是多个,所以又给接收人一单独的表,(这种方案好还是全部都放到一张表里好点呢?)2张表的字段如下:message_id是第一张表的主键,如果收件人有…

java设计模式之道文字版,Java Web设计模式之道 PDF

资源名称:Java Web设计模式之道 PDF第一部分 仙人指路——设计模式简介第1章 设计模式概述1.1 设计模式是什么1.2 软件设计模式的发展历程1.3 作者阐述软件设计模式的主要方式第二部分 设计红宝书——设计模式原则详解第2章 设计原则之开闭原则2.1 何谓开闭原则2.2 …

java上传excel文件代码,求java把上传文件的excel表中数据存入数据库中.实现录入的代码?...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼CREATE TABLE [dbo].[p_bom_user_info] ([ID] varchar(50) NULL ,[SESAID] varchar(200) NULL ,[StaffNo] varchar(200) NULL ,[NotesID] varchar(200) NULL ,[ACName] varchar(100) NULL ,[BusinessUnit] varchar(100) NULL ,[Com…

php开发视频播放顺序,请问关于php代码运行顺序问题

麻烦会的朋友帮忙回答下 以下的问题, 谢谢啦。在网上下载了套代码。 如下 admin.php 文件:对于以下这段代码, 究竟代码是怎么跑的呢?也就是比如说 以下的代码,什么时候 才会跑 if ($device ipad) 这句代码呢&#xff…

python文件操作模式是什么,python --文件操作模式详解

#f open(r"aaa/a.txt",modert) # f的值是一种变量,占用的是应用程序的内存空间,此时牵扯的是两个方面的资源#print(f)##2.操作文件:读/写文件,应用程序对文件的读写请求都是向操作系统调用,然后由操作系统控制把硬盘把输入读入内存…

php 中文转成url,php字符转URL地址的函数

php字符转URL地址的函数php提供了urlencode()、urldecode()、rawurlencode()、rawurldecode()函数了,利用它就可以直接转换URL地址。下面是小编为大家带来的.php字符转URL地址的函数,欢迎阅读。php字符转URL地址的函数代码如下function tourl($str) {$st…

php和ajax的同步和异步请求,ajax 同步请求和异步请求的差异分析_javascript技巧

ajax同步和异步的差异, 先看2段代码:代码一:Synchronize function(url,param) {function createXhrObject() {var http;var activeX [ "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP" ];try …

matlab变量由非标量,matlab中的if语句

有条件性地执行语句语法if expressionstatementsend描述MATLAB计算表达式,如果产生一个逻辑真或者非零结果,然后就执行一条或者多条MATLAB命令语句。当有嵌套if时,每一个if必须和一个相应的end匹配。当你在if语句里面嵌套使用else if或者else…

如何用oracle查看内存使用情况,oracle运维08内存使用情况分析查看

1、SGA、PGA应用状况查问;select name,total,round(total-free,2) used, round(free,2) free,round((total-free)/total*100,2) pctused from(select SGA name,(select sum(value/1024/1024) from v$sga) total,(select sum(bytes/1024/1024) from v$sgastat where …

rodbc 连接oracle,R語言 使用RODBC連接oracle數據庫

使用R語言有多種包可以連接oracle數據庫,我今天在這里講一下使用使用RODBC連接oracle數據庫。1. 如果你的本地是windows系統的話,你需要安裝oracle客戶端。2. 然后需要在ODBC管理者界面配置你要進行連接的數據庫數據及使用的驅動等信息。如下圖所示&…

oracle实验七 答案,Oracle表的常用查询实验(七)

Oracle表的常用查询实验(七)1.问题描述:有一个商品信息表,该表反应了各种商品的销售情况,一个产品是按照gid和gname两个字段来区分的,一个产品可能会有多个型号。create table T_Goods(Id int primary key,GId varchar2(10) not n…

调用oracle常用方法,区分Oracle和SQL Server常用函数调用方法

一、数学函数1.绝对值S:select abs(-1) valueO:select abs(-1) value from dual2.取整(大)S:select ceiling(-1.001) valueO:select ceil(-1.001) value from dual3.取整(小)S:select floor(-1.001) valueO:select floor(-1.001) value from dual4.取整(截取)S:select cast(-1.…

oracle函数大全指数运算,Oracle 函数大全(字符串函数,数学函数,日期函数,逻辑运算函数,其他函数),该如何解决...

当前位置:我的异常网 Oracle开发 Oracle 函数大全(字符串函数,数学函数,日期函数,Oracle 函数大全(字符串函数,数学函数,日期函数,逻辑运算函数,其他函数),该如何解决www.myexceptions.net 网…

oracle ogg00423,【案例】Oracle报错PLS-00378 PLS-00439产生原因和MOS官方解决办法

【案例】Oracle报错PLS-00378 PLS-00439产生原因和MOS官方解决办法时间:2016-11-12 21:31 来源:Oracle研究中心 作者:代某人 点击:次天萃荷净PLS-00378此版本的PL / SQL编译单元无效原因:编译单元是一个文件,其中包含的PL / SQL传递给编译器的源代…