如何解决其中的可见性有序性导致的问题,这也就引出来了今天的主角——Java 内存模型。

一、什么是 Java 内存模型?

导致可见性的原因是缓存,导致有序性的原因是编译优化,那解决可见性、有序性最直接的办法就是禁用缓存和编译优化,但这样虽然解决了问题,但也导致带来的性能优化都没了。

因此,解决方案是:提出一套规则和方法,是程序员能在该禁用的时候禁用,不该禁用的时候不禁用。

Java 内存模型规范就是来解决这个问题的 —— 提供按需禁用缓存和编译优化的方法

具体来说,这些方法包括 volatile、synchronized 和 final 三个关键字,以及六项 Happens-Before 规则,这也正是本期的重点内容。

二、Happens-Before 规则

Q:如何理解 Happens-Before 呢?

A:前面一个操作的结果对后续操作是可见的。但不能理解为前一个操作发生在后续操作的前面。

只要最终语义是对的,编译器怎么优化都行。

1、程序的顺序性规则

这条规则是指在一个线程中,按照程序顺序,前面的操作 Happens-Before 于后续的任意操作。

2、volatile 变量规则

这条规则是指对一个 volatile 变量的写操作, Happens-Before 于后续对这个 volatile 变量的读操作。

3、传递性

这条规则是指如果 A Happens-Before B,且 B Happens-Before C,那么 A Happens-Before C。

4、管程中锁的规则

这条规则是指对一个锁的解锁 Happens-Before 于后续对这个锁的加锁。

5、线程 start() 规则

这条是关于线程启动的。它是指主线程 A 启动子线程 B 后,子线程 B 能够看到主线程在启动子线程 B 前的操作。

6、线程 join() 规则

它是指主线程 A 等待子线程 B 完成(主线程 A 通过调用子线程 B 的 join() 方法实现),当子线程 B 完成后(主线程 A 中 join() 方法返回),主线程能够看到子线程的操作。当然所谓的“看到”,指的是对共享变量的操作。

疑惑

Q:volatile、synchronized 和 final 能理解是提供给程序员用的,六项 Happens-Before 规则是约束谁的呢?

A:这是给程序员的保障,按照提供的规则写,就能保证 Happens-Before 的语义。

参考文章:

Java内存模型以及happens-before规则

【Java并发入门】02 Java内存模型:看Java如何解决可见性和有序性问题的更多相关文章

  1. 02 | Java内存模型:看Java如何解决可见性和有序性问题

    什么是 Java 内存模型? 导致可见性的原因是缓存,导致有序性的原因是编译优化,那解决可见性. 有序性最直接的办法就是禁用缓存和编译优化,但是这样问题虽然解决了,我们程序的性能可就堪忧了.   合理 ...

  2. Java并发(3):volatile及Java内存模型

    Java 语言中的 volatile 变量可以被看作是一种“程度较轻的 synchronized“:与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少,但 ...

  3. 掌握Java的内存模型,你就是解决并发问题最靓的仔

    摘要:如果编写的并发程序出现问题时,很难通过调试来解决相应的问题,此时,需要一行行的检查代码,这个时候,如果充分理解并掌握了Java的内存模型,你就能够很快分析并定位出问题所在. 本文分享自华为云社区 ...

  4. 并发研究之Java内存模型(Java Memory Model)

    Java内存模型JMM java内存模型定义 上一遍文章我们讲到了CPU缓存一致性以及内存屏障问题.那么Java作为一个跨平台的语言,它的实现要面对不同的底层硬件系统,设计一个中间层模型来屏蔽底层的硬 ...

  5. 高效并发一 Java内存模型与Java线程(绝对干货)

    高效并发一 Java内存模型与Java线程 本篇文章,首先了解虚拟机Java 内存模型的结构及操作,然后讲解原子性,可见性,有序性在 Java 内存模型中的体现,最后介绍先行发生原则的规则和使用. 在 ...

  6. 【JVM】JVM内存结构 VS Java内存模型 VS Java对象模型

    原文:JVM内存结构 VS Java内存模型 VS Java对象模型 Java作为一种面向对象的,跨平台语言,其对象.内存等一直是比较难的知识点.而且很多概念的名称看起来又那么相似,很多人会傻傻分不清 ...

  7. 【转】JVM内存结构 VS Java内存模型 VS Java对象模型

    JVM内存结构 我们都知道,Java代码是要运行在虚拟机上的,而虚拟机在执行Java程序的过程中会把所管理的内存划分为若干个不同的数据区域,这些区域都有各自的用途. 其中有些区域随着虚拟机进程的启动而 ...

  8. JAVA内存模型(Java Memory Model ,JMM)

    http://blog.csdn.net/hxpjava1/article/details/55189077 JVM有主内存(Main Memory)和工作内存(Working Memory),主内存 ...

  9. 硬件内存模型到 Java 内存模型,这些硬核知识你知多少?

    Java 内存模型跟上一篇 JVM 内存结构很像,我经常会把他们搞混,但其实它们不是一回事,而且相差还很大的,希望你没它们搞混,特别是在面试的时候,搞混了的话就会答非所问,影响你的面试成绩,当然也许你 ...

  10. 区分 JVM 内存结构、 Java 内存模型 以及 Java 对象模型 三个概念

    本文由 简悦 SimpRead 转码, 原文地址 https://www.toutiao.com/i6732361325244056072/ 作者:Hollis 来源:公众号Hollis Java 作 ...

随机推荐

  1. 1 Java内存区域管理

    目录 1 关于自动内存管理 2 运行时数据区域 2.1 程序计数器 2.2 虚拟机栈 2.2.1 局部变量表 2.2.2 操作数栈 2.3 本地方法栈 2.4 堆 2.5 方法区 2.5.1 运行时常 ...

  2. P1829 [国家集训队]Crash的数字表格

    P1829 [国家集训队]Crash的数字表格 原题传送门 前置芝士 莫比乌斯反演 乘法逆元 数论分块 正文 //补充:以下式子中的除法均为整除 由题目可以得知,这道题让我们所求的数,用一个式子来表达 ...

  3. 2.云原生之Docker容器环境安装实践

    转载自:https://www.bilibili.com/read/cv15181036/?from=readlist 官方一键安装脚本 补充时间:[2020年4月22日 11:00:59] 一键安装 ...

  4. nginx反向代理Grafana

    官方文旦地址:https://grafana.com/tutorials/run-grafana-behind-a-proxy/ 一级路径 只需要修改nginx配置文件 # this is requi ...

  5. windows bat文件设置环境变量

    主要是SET和SETX这个两个命令 SETX 永久设置用户环境变量 SETX /M 永久设置系统环境变量 SET 临时设置用户环境变量 SET /M 临时设置系统环境变量

  6. 4.maven私服nexus2迁移到nexus3

    注意,本文讲解的是针对我们原来所用的nexus2.14.5版本的升级配置流程,如果您的老私服版本并不是这个,那么请先参考这里:升级兼容性 – Repository Manager 2到3.选定对应可升 ...

  7. #css#如何使用hover,实现父对子的样式改变?

    思路及做法: 鼠标移动到父盒子的时候, 里面所有的子盒子的样式都发生变化的, 只需要直接在hover后面加上空格, 并且加上子盒子的类名 ,里面再写其他样式 .父盒子的类名:hover .子盒子的类名 ...

  8. 修改-Python函数-2

    一.导入 $$f ( x , y ) = 2 x + 3 y$$ 上面括号里面的就是数学公式里的自变量,自变量就相当于函数里的参数. 二.为什么要有参数 如果一个大楼里有两种尺寸不一的窗户,显然在没有 ...

  9. 编程架构演化史:远古时代,从打孔卡(Punched Card)开始

    回想读书时记录到书本里的打孔纸带编程,到初学编程接触到的C语言高级编程,再到C++.Java面向对象语言产生:从面向过程系统设计 到面向对象系统设计:从三层结构到MVC.MVP.MVVM:从主机到虚拟 ...

  10. 带你认识JDK8中超nice的Native Memory Tracking

    摘要:从 OpenJDK8 起有了一个很 nice 的虚拟机内部功能: Native Memory Tracking (NMT). 本文分享自华为云社区<Native Memory Tracki ...