深入理解java内存模型--读书笔记
深入理解java内存模型
java内存模型的抽象
java线程之间的通信由java内存模型(JMM)控制,JMM决定一个线程对共享变量的写入何时对另一个线程可见
从抽象的角度来看,JMM决定了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main memeory)中,每个线程都有一个私有的本地内存(local memeory),本地内存中存储了该线程以读/写共享变量的副本.本地内存是JMM的一个抽象概念,并不真实存在.
假设: 线程A与线程B之间如要通信的话,必须要经历下面2个步骤:
- 首先,线程A把本地内存A中更新过的共享变量刷新到主内存中去
- 然后,线程B到主内存中去读取线程A之前已更新过的共享变量

重排序
- 编译器优化的重排序。编译器在不改变单线程予以的前提下,可以重新按排序语句的执行顺序。
- 指令级并行的重排序。现代处理器采用了指令级并行技术来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。
- 内存系统的重排序。由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。
为了保证内存可见性,java编译器在生成指令序列的适当位置会插入内存屏障指令来进制特定类型的处理器重排序。JMM把内存屏障指令分为下列四类:
| 屏障类型 | 指令事例 | 说明 |
|---|---|---|
| LoadLoad Barriesrs | Load1;LoadLoad;Load2 | 确保Load1数据的装载,之前于Load2及所有后续装载指令的装载 |
| StoreStore Barriers | Store1;StoreStore;Store2 | 确保Store1数据对其他处理器可见(刷新到内存),之前于Store2及所有后续存储指令的储存 |
| LoadStore Barriesrs | Load1;LoadStore;Store2 | 确保Load1数据装载,之前于Store2及所有后续的存储指令刷新到内存 |
| StoreLoad Barriers | Store1;StoreLoad;Load2 | 确保Store1数据对其他处理器变得可见(指刷新到内存),之前于Load2及所有后续装载指令的装载。StoreLoad Barriers会使该屏障之前的所有内存访问指令(存储和装载指令)完成之后,才执行该屏障之后的内存访问指令。 |
StoreLoad Barriers同事具有其他三个屏障的效果。现代的多处理器大都支持该屏障(其他类型的屏障不一致被所有处理器支持)。
happens-before
从JDK5开始,java使用新的JSR-133内存模型。在JMM中,如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须要存在happens-before关系。这里提到的两个操作既可以是在一个线程之内,也可以是在不同线程之内。
规则如下:
- 程序顺序规则:一个线程中的每个操作,happens-before于该线程中的任意后续操作。
- 监视器锁规则:对一个监视器的解锁,happens-before于随后对这个监视器的加锁
- volatile变量规则:对一个volatile域的写,happens-before于任意后续对这个volatile域的读。
- 传递性:如果A happens-before B,且B happens-before C,那么A happens-before C。
注意:两个操作之间具有happens-before关系,并不意味着前一个操作必须要在后一个操作之前执行,happens-before仅仅要求前一个操作(执行的结果)对后一个操作可见,且前一个操作按顺序排在第二操作之前。
Volatile
public class MyTest1 {
volatile long vl = 0L; // 使用volatile声明64位的long型变量
public void set(long l) {
vl = l; //单个volatile变量的写
}
public void getAndIncrement() {
vl++; //复合(多个)volatile变量的读/写
}
public long get() {
return vl; //单个volatile变量的读
}
}
这个程序在语义上和下面程序等价:
public class MyTest1 {
long vl = 0L; // 声明64位的long型变量
public synchronized void set(long l) {
vl = l;
}
public void getAndIncrement() {
long temp = get();
temp+=1L;
set(temp);
}
public synchronized long get() {
return vl;
}
}
锁的happens-before规则保证释放锁和获取锁的两个线程之间的内存可见性,这意味着对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入。
volatile变量自身具有下列特性:
- 可见性。对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入。
- 原子性:对任意单个volatile变量的读、写具有原子性,但类似于volatile++这种复合操作不具有原子性。
volatile读的内存语义如下:
当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效。线程接下来将从主内存中读取共享变量。
锁
锁释放和获取的内存语义
当线程释放锁时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中。
当线程获取锁时,JMM会把该线程对应的本地内存置为无效。从而使得被监视器保护的临界区代码必须要从主内存中去读取共享变量。
final
对于final域,编译器和处理器要遵守两个重排序规则:
- 在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序
- 初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能重排序。
深入理解java内存模型--读书笔记的更多相关文章
- 《Java并发编程实战》第十六章 Java内存模型 读书笔记
Java内存模型是保障多线程安全的根基,这里不过认识型的理解总结并未深入研究. 一.什么是内存模型,为什么须要它 Java内存模型(Java Memory Model)并发相关的安全公布,同步策略的规 ...
- 《深入理解 Java 内存模型》读书笔记

概要 文章是<深入理解Java内容模型>读书笔记,该书总共包括了3部分的知识. 第1部分,基本概念 包括“并发.同步.主内存.本地内存.重排序.内存屏障.happens before规则. ...
- 深入理解 Java 内存模型(转载)
摘要: 原创出处 http://www.54tianzhisheng.cn/2018/02/28/Java-Memory-Model/ 「zhisheng」欢迎转载,保留摘要,谢谢! 0. 前提 &l ...
- 【并发编程】一文带你读懂深入理解Java内存模型(面试必备)
并发编程这一块内容,是高级资深工程师必备知识点,25K起如果不懂并发编程,那基本到顶.但是并发编程内容庞杂,如何系统学习?本专题将会系统讲解并发编程的所有知识点,包括但不限于: 线程通信机制,深入JM ...
- 深入理解java内存模型系列文章
转载关于java内存模型的系列文章,写的非常好. 深入理解java内存模型(一)--基础 深入理解java内存模型(二)--重排序 深入理解java内存模型(三)--顺序一致性 深入理解java内存模 ...
- 【Todo】【转载】深入理解Java内存模型
提纲挈领地说一下Java内存模型: 什么是Java内存模型 Java内存模型定义了一种多线程访问Java内存的规范.Java内存模型要完整讲不是这里几句话能说清楚的,我简单总结一下Java内存模型的几 ...
- 深入理解Java内存模型(一)——基础(转)
转自程晓明的"深入理解Java内存模型"的博客 http://www.infoq.com/cn/articles/java-memory-model-1 并发编程模型的分类 在并发 ...
随机推荐
- Mint-ui全局引入
1.Mint-ui在全局引入之后,在组件中使用其中的js函数,如toast() this.$toast('在全局引入之后可以直接在this.$toast中使用')
- Element-ui安装之MessageBox详解
1.首先根据官方文档进行Element-ui的安装,这个过程很简单(通过webpack-simple) 1) vue init webpack-simple element-ui 2) cd elem ...
- Python笔记【4】_字典学习
#!/usr/bin/env/python #-*-coding:utf-8-*- #Author:LingChongShi #查看源码Ctrl+左键 ''' dict:字典以“{}”包围,以“键:值 ...
- SQL经典练习题50--mysql
--1.学生表 Student(Sid,Sname,Sage,Ssex)? --Sid 学生编号,Sname 学生姓名,Sage 出生年月,Ssex 学生性别 --2.课程表? Course(Cid, ...
- SLAM方向国内有哪些优秀公司?
计算机视觉life为读者整理了国内几十家涉及SLAM的优秀公司,涵盖自动驾驶.仓储机器人.服务机器人.无人机.AR.芯片相机等领域. 一 自动/辅助驾驶: 1.百度: 主要产品:自动驾驶软件 百度智能 ...
- HDU 3879 && BZOJ 1497:Base Station && 最大获利 (最大权闭合图)
http://acm.hdu.edu.cn/showproblem.php?pid=3879 http://www.lydsy.com/JudgeOnline/problem.php?id=1497 ...
- MySQL错误:The user specified as a definer (XXX@XXX) does not exist (1449错误)最简解决方案
背景:从同事处通过备份和还原备份方法导入mysql数据库,导入成功后启动项目,发现出现以下错误:The user specified as a definer (XXX@XXX) does not e ...
- Oracle Goldengate是如何保证数据有序和确保数据不丢失的?
工作中一直在用Oracle 的中间件Oracle GondenGate 是如何保证消息的有序和不丢失呢? Oracle GoldenGate逻辑架构 首先,先看一下Oracle GoldenGate ...
- c++学习书籍推荐《The C++ Programming Language第四版》下载
百度云及其他网盘下载地址:点我 作者简介 Bjarne Stroustrup is the designer and original implementer of C++, the author o ...
- 两个域名同时访问一个tomcat下的两个项目
两个域名,分别映射一个TOMCAT底下,两个应用. 分三个步骤完成. 1.域名与IP的解析,此步骤在万网等机构完成. 2.APACHE的httpd.conf的配置 <VirtualHost *: ...