jvm(6):JMM
typora-root-url: ./
CPU多核并发缓存架构

JMM(Java线程内存模型)底层实现原理
基于CPU缓存模型建立的,屏蔽掉了底层不同计算机的区别。

所有的共享变量都存储在主内存。每条线程还有自己的工作内存。线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的变量。
JMM数据原子操作
- read(读取):从主内存读取数据到工作内存中,以便load
- load(载入):将主内存读取到的数据写入工作内存
- use(使用):从工作内存读取数据来计算
- assign(赋值):将计算好的值重新赋值到工作内存中
- store(存储):将工作内存数据写入主内存
- write(写入):将store的变量值赋值给主内存中的变量
- lock(锁定):将主内存变量加锁,标识为线程独占状态
- unlock(解锁):将主内存变量解锁,解锁后其他线程可以锁定该变量
深入汇编语言底层理解volatile关键字
共享变量改变,但是副本没有改变!
例子:Java
private static boolean initFlag = false;
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("waiting data...");
while(!initFlag) {
}
System.out.println("======success"); // 这句不会输出
}
}).start();
Thread.sleep(2000);
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("prepareing data...");
initFlag = true;
System.out.println("======prepare data end...");
}
}).start();
}
JMM缓存不一致问题-修改:
private static volatile boolean initFlag = false;
System.out.println("======success"); //打印成功
简单理解为副本之间可以互相感知共享变量的改变,保证可变性。(线程之间通信)
volatile实现原理

总线加锁(性能太低)
CPU从主内存读取数据到高速缓存,会在总线对这个数据加锁,这样其他CPU没法去读或写这个数据,直到这个CPU使用完数据释放锁之后其他CPU才能读取该数据。
MESI缓存一致性协议
多个CPU从主内存读取同一个数据到各自的高速缓存,当其中某个CPU修改了缓存里的数据,该数据会马上同步回主内存,其它CPU通过总线嗅探机制可以感知到数据的变化从而将自己缓存里的数据失效。
volatile缓存可见性实现原理
底层实现主要是通过汇编lock前缀指令,它会锁定这块内存区域的缓存(缓存行锁定)并回写到主内存。
并发编程:可见性、原子性与有序性
有序性
for(int i = 0; i < 100000; i++) {
x = 0;
y = 0;
Thread one = new Thread(new Runnable() {
public void run() {
int a = y; // 3
x = 1; // 1
}
});
Thread other = new Thread(new Runnable() {
public void run() {
int b = x; // 4
y = 1; // 2
}
})
}
指令重排,导致程序问题。volatile!提示不要指令重排。
可见性
可见性,指当一条线程修改了这个变量的值,新值对于其他线程来说是可以立即得知的。
原子性
volatile保证可见性与有序性,但是不保证原子性,保证原子性需要借助synchronized这样的锁机制。
private static volatile int num = 0;
public static void main(String[] args) {
Thread[] threads = new Thread[10];
for(Thread t : threads) {
t = new Thread(new Runnable() {
@Override
public void run() {
for(int i = 0; i < 1000; i++) {
increase(); // num++;
}
}
});
t.start();
}
for(Thread t : threads) {
t.join();
}
System.out.println(num); // <=10000
}
======字节码在这里=====
getstatic
iconst_1
iadd
putstatic
在自己加值的时候(iconst_1或者iadd),其他线程可能已经把值加上去了,所以自己加的是一个过期的数据。
总结
volatile的两个语义:
- 可见性
- 禁止指令重排序优化
jvm(6):JMM的更多相关文章
- 深入理解JVM内幕:从基本结构到Java 7新特性
转自:http://www.importnew.com/1486.html 每个Java开发者都知道Java字节码是执行在JRE((Java Runtime Environment Java运行时环境 ...
- JVM总括:目录
JVM总括:目录 JVM总括一-JVM内存模型 JVM总括二-垃圾回收:GC Roots.回收算法.回收器 JVM总括三-字节码.字节码指令.JIT编译执行 JVM总括四-类加载过程.双亲委派模型.对 ...
- JVM内存:年轻代、老年代、永久代(推荐 转)
参考文章: 1.Java 新生代.老年代.持久代.元空间 2.Java内存与垃圾回收调优 3.方法区的Class信息,又称为永久代,是否属于Java堆? Java 中的堆是 JVM 所管理的最大的一块 ...
- JVM(三):深入分析Java字节码-上
JVM(三):深入分析Java字节码-上 字节码文章分为上下两篇,上篇也就是本文主要讲述class文件存在的意义,以及其带来的益处.并分析其内在构成之一 ---字节码,而下篇则从指令集方面着手,讲解指 ...
- JVM(八):Java 对象模型
JVM(八):Java 对象模型 本文将学习对象是如何创建的,对象的内存布局,以及如何定位访问一个对象. 对象创建 当虚拟机碰到一个new指令时,首先检查指令参数能否在常量池中定位一个类的符号引用,并 ...
- JVM(十一):内存分配
JVM(十一):内存分配 在前面的章节中,我们花了大量的篇幅去介绍 JVM 内的内存布局.对象在内存中的状态.垃圾回收的算法和具体实现等.今天让我们探讨一下对象是如何分配内存的. 堆内存划分 前面说过 ...
- 深入理解JVM内幕:从基本结构到Java 7新特性[转]
英文原文:cubrid,编译:ImportNew - 朱伟杰 译文链接:http://www.importnew.com/1486.html [如需转载,请在正文中标注并保留原文链接.译文链接和译者等 ...
- Java并发指南5:JMM中的final关键字解析
本文转载自互联网,侵删 与前面介绍的锁和volatile相比较,对final域的读和写更像是普通的变量访问.对于final域,编译器和处理器要遵守两个重排序规则: 在构造函数内对一个final域的 ...
- JVM探秘:MAT分析内存溢出
本系列笔记主要基于<深入理解Java虚拟机:JVM高级特性与最佳实践 第2版>,是这本书的读书笔记. MAT是分析Java堆内存的一个工具,全称是 The Eclipse Memory A ...
随机推荐
- Fabric智能合约(base)
这里的智能合约仅包含Init函数和Invoke函数. 为什么一定是这两个方法? 因为在源码中的智能合约模块有这样的接口,如果要完成智能合约的相关编程,就需要实现源码中定义的接口,接口中定义了这两个方法 ...
- 用友UAP NC 单据节点_打开参照字段的问题_从打不开参照放大镜_到成功打开了但是取不到值_到修复成功
项目的这个功能是17年开发的,但是当时没有测试通过,今年拿出来测试(通过后会上线). 有两个表数据一开始只打算用来计算时查询,没打算放到目标单据中做表体参照字段.后来改细节问题后放到目标单据中做参照字 ...
- 婴儿潮一代\千禧一代\X一代\Z一代含义
(一)婴儿潮一代 婴儿潮一代是指各国的生育高峰期.每个时期的婴儿潮一代都会给各国经济带来不小的刺激作用,但同样的当他们退休时也会给政府的养老保险带来巨大的压力. 在中国,从统计数据来看生育高峰出现在1 ...
- VAR向量自回归模型学习笔记2
向量自回归模型 今天的你 和昨天的你 和前天的你,是否具有相关性. 1. 定义 向量自回归(VAR,Vector Auto regression)分析联合内生变量间的动态关系 联合:n个变量间的相互影 ...
- JavaScript实现动态打字效果
废话不多说,上代码~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset=&qu ...
- java读取解析application.yml
java读取解析application.yml 不用依赖spring容器,可单独使用. bug已修改... 第一步.首先要2个jar <!-- properties和yaml格式化 --> ...
- 【Unity|C#】基础篇(21)——常用类
- Leetcode Week1 Regular Expression Matching
Question Given an input string (s) and a pattern (p), implement regular expression matching with sup ...
- Dijkstra算法依据项目改进版,输出路径
package dijkstra; import java.util.ArrayList; public class Dijkstra { ; /*private static int[][] Gra ...
- 【你不知道的javaScript 上卷 笔记5】javaScript中的this词法
function foo() { console.log( a ); } function bar() { var a = 3; foo(); } var a = 2; bar(); 上面这段代码为什 ...