1.JMM (Java Memory Model)内存模型相关概念
模型图:
可以对应下面这张图:
这张图告诉我们在线程运行的时候有一个内存专用的一小块内存,当Java程序会将变量同步到线程所在的内存,这时候会操作工作内存中的变量,而线程 中变量的值何时同步回主内存是不可预期的。但同时Java内存模型又告诉我们通过使用关键词“synchronized”或“volatile”可以让 Java保证某些约束:
“volatile” — 保证读写的都是主内存的变量
“synchronized” — 保证在块开始时都同步主内存的值到工作内存,而块结束时将变量同步回主内存.
本地内存是什么,数据存在哪里?
1、java内存模型的抽象概念
2、并不在堆中,而是在cpu中的物理cache
可参考:http://www.cnblogs.com/dolphin0520/p/3920373.html 第一部分
Intel 的MESI协议,MESI协议保证了每个缓存中使用的共享变量的副本是一致的。它核心的思想是:当CPU写数据时,如果发现操作的变量是共享变量,即在其他CPU中也存在该变量的副本,会发出信号通知其他CPU将该变量的缓存行置为无效状态,因此当其他CPU需要读取这个变量时,发现自己缓存中缓存该变量的缓存行是无效的,那么它就会从内存重新读取。
跨核访问需要通过Memory Controller
问题:为什么需要这样?
访问快!!
就像:访问mysql时,常用结果会被缓存到redis等缓存产品一样;
Cpu与内存的交互速度远慢于cpu的运算速度为了提高处理速度,先进系统内存的数据读到内存缓存(L1,L2,L3等)
缓存行(Cache line)
为了高效地存取缓存, 不是简单随意地将单条数据写入缓存的. 缓存是由缓存行组成的, 典型的一行是64字节.
读者可以通过下面的shell命令,查看cherency_line_size就知道知道机器的缓存行是多大。
cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size
查看下面这台机器: 16个cpu 每个为4核 缓存行64字节
2.并发编程几个重要概念
2.1 三个特性
在并发编程中,我们通常会遇到以下三个问题:原子性问题,可见性问题,有序性问题。我们先看具体看一下这三个概念:
1).原子性
原子性:即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。
2).可见性
可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
3).有序性
有序性:即程序执行的顺序按照代码的先后顺序执行。
2.2 重排序
JMM属于语言级的内存模型,它确保在
不同的编译器和不同的处理器平台之上,
通过禁止特定类型的编译器重排序和处理器重排序,为程序员提供一致的内存可见性保证。
对于编译器冲排序,JMM的编译器重排序规则会禁止特定类型的编译器重排序(不是所有的编译器重排序都要禁止)。
对于处理器重排序,JMM的处理器重排序规则会要求java编译器在生成指令序列时,插入特定类型的
内存屏障(memory barriers,intel称之为memory fence)指令,通过内存屏障指令来禁止特定类型的处理器重排序(不是所有的处理器重排序都要禁止)。
引申:
在执行程序时为了提高性能,编译器和处理器常常会对指令做重排序。重排序分三种类型:
- 编译器优化的重排序。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。
- 指令级并行的重排序。现代处理器采用了指令级并行技术(Instruction-Level Parallelism, ILP)来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。
- 内存系统的重排序。由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。
上述的1属于编译器重排序,2和3属于处理器重排序。这些重排序都可能会导致多线程程序出现内存可见性问题。
2.3 内存屏障memory Barriers
内存屏障类型
volatile语义中内存屏障的插入策略
在每个volatile写前面插入SS
在每个volatile写后面插入SL
在每个volatile读后面插入LL,插入LS
连续的操作之间多余的内存屏障会由编译器觉得是否省略。
同时,不同的操作系统所允许的重排序类型也不尽相同,例如x86只允许sl重排序,所以其实只需要加这一种内存屏障即可。
3.volatile,final,synchronized锁语义
3.1 volatile内存语义
允许线程访问共享变量。为了确保共享变量能够被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量。
1、某些情况比锁更加方便
2、内存模型确保线程可以看到的变量的值是一致的
Lock前缀的指令
java -XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*类名.方法名 类名
1、将当前处理器缓存行的数据写回系统内存
2、使其他CPU里缓存了该内存地址的数据无效
缓存一致性协议:每个处理器嗅探总线上传播的数据来检查自己缓存的值是否过期,当发现缓存行对应的内存地址被修改,会将当前行设置成无效状态,再次操作,会重新从系统内存中读取。
可见性:对一个volatile变量的读,总能看到(任意线程)对这个变量最后的写入。
原子性:对任意单个volatile变量的读/写具有原子性,但类似于volatile++这种复合操作不具有原子性,obj = new Object();也不是原子性
3.2 final域的内存语义
final域,编译器和处理器遵守两个重排序规则
1、在构造器内对final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序。SS屏障
2、初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能重排序。LL屏障
防止域从构造器中溢出。旧的内存模型中,可能看到final域的值为0,稍后由于初始化,发现final域的值变为1,这是比较尴尬的,所有JSR-133增强了final的语义,只要对象正确构造(被构造对象的引用在构造器中没有溢出),那么不需要使用同步,就可以保证任意线程都能看到final域在构造器中被初始化之后的值。
同时x86处理器只允许SL重排序,所以final语义的实现其实无需增加内存屏障。
3.3 锁的内存语义
待续......
1.解决以下问题:
1).JMM内存模型中本地缓存和工作内存是什么关系?
2).重排序在什么时候进行?(JIT编译优化时进行)
3).什么是内存屏障Memory Barriers,内存屏障帮我做了什么?4).内存屏障的4种插入形式?
5).原子性 可见性 重排序 顺序一致性的解释?
6).volatile,synchronized,final的语义
7).as-id-serial,happens-before的语义
相关文章:
参考:
2.Java并发编程:volatile关键字解析
3.并发编程网: JAVA内存模型
- 大小: 12.1 KB
- 大小: 49.4 KB
- 大小: 29.7 KB
- 大小: 22.7 KB
- 大小: 13.4 KB
- 大小: 2.9 KB
- 大小: 35.3 KB
- 大小: 9.6 KB
- 大小: 7.3 KB
- 大小: 21 KB
分享到:
相关推荐
Java内存模型(JMM)是Java虚拟机规范的一部分,用于定义程序中各个线程对共享变量的访问规则,包括线程之间的通信、内存可见性和原子性等问题。 首先,Java内存模型规定了三个主要区域:程序计数器、虚拟机栈、...
Java内存模型,简称JMM(Java Memory Model),是Java虚拟机规范中定义的一个抽象概念,它描述了在多线程环境下,如何保证各个线程对共享数据的一致性视图。JMM的主要目标是定义程序中各个变量的访问规则,以及在...
Java内存模型,简称JVM内存模型,是Java虚拟机(JVM)运行时的核心组成部分,它定义了如何在多线程环境下共享数据以及确保数据一致性。深入理解Java内存模型对于优化程序性能、避免并发问题至关重要。 首先,让我们...
《深入理解Java虚拟机》是一本深度探讨Java虚拟机(JVM)的著作,涵盖了JVM性能调优、内存模型以及虚拟机原理等多个关键领域。本文将基于这些主题,详细阐述其中的重要知识点。 首先,我们要了解Java虚拟机(JVM)...
Java内存模型(Java Memory Model,JMM)是Java虚拟机(JVM)中的一种内存模型,它描述了程序中各个变量之间的关系,以及在实际计算机系统中将变量存储到内存和从内存中取出变量这样的底层细节。JMM允许编译器和缓存...
近期,在诚信通开源研究小组的专题学习分享会上,我们针对Java内存模型(JMM)进行了深入探讨,现将JMM相关的一些核心概念进行梳理,以便更好地理解和把握JMM的基本原理。 #### 第一问:JMM是干什么的? JMM (Java ...
6. **JVM内存模型**:Java内存模型(JMM,Java Memory Model)定义了线程如何访问和修改共享变量,以及如何保证内存可见性和一致性。 7. **异常处理与线程**:JVM支持多线程,每个线程有自己的虚拟机栈和程序计数器...
2. **内存模型**:书中详细阐述了Java内存模型(JMM),包括堆内存、栈内存、方法区、本地方法栈和程序计数器等组成部分。了解这些内存区域的分配与回收机制,有助于避免内存泄漏和提高程序性能。 3. **垃圾收集与...
在说Java内存模型之前,我们先说一下Java的内存结构,也就是运行时的数据区域:Java虚拟机在执行Java程序的过程中,会把它管理的内存划分为几个不同的数据区域,这些区域都有各自的用途、创建时间、销毁时间
本书详细阐述了Java虚拟机的架构、内存模型以及执行机制。以下是一些关键的知识点: 1. **类加载机制**:Java类的生命周期包括加载、验证、准备、解析和初始化五个阶段。类加载器负责找到类的二进制数据并将其转换...
6. **内存模型与并发**:Java内存模型(JMM)定义了线程之间共享变量的访问规则,确保正确同步和内存可见性。它涉及到volatile变量、synchronized关键字、final字段的语义以及线程交互的内存操作。 7. **异常处理**...
《Java虚拟机规范(Java_SE_7)》详细阐述了Java SE 7版本的JVM工作原理、内存模型以及指令集等关键概念。这份文档对于理解Java程序的执行机制、性能优化和故障排查具有极高的价值。 1. **JVM结构**:JVM由类加载器、...
8. **JVM内存模型**:Java内存模型(Java Memory Model, JMM)规定了共享变量在多线程环境下的可见性和有序性,理解JMM对于编写正确且高效的并发程序至关重要。 9. **垃圾收集算法**:包括标记-清除、复制、标记-...
5. **内存模型(JMM)**:Java内存模型规定了线程如何访问和修改共享变量,确保多线程环境下的正确性。熟悉volatile、synchronized、final关键字在内存模型中的作用,以及happens-before原则,有助于编写并发安全的...
除了堆和栈之外,Java程序还可能使用本机内存(Native Memory),这通常是指Java虚拟机之外的内存,例如直接缓冲区(Direct Buffer)所使用的内存。直接缓冲区是在Java NIO(New I/O)包中引入的,用于提高I/O操作的...
Java虚拟机是Java平台的核心组成部分,它负责执行字节码,提供类加载、内存管理、线程调度以及垃圾回收等服务。JVM的跨平台特性使得Java程序具备“一次编写,到处运行”的能力。 二、字节码与类加载 Java源代码经过...
本PPT着重讲解了Java虚拟机的基础知识,包括其工作原理、内存模型、类加载机制以及垃圾收集等方面。 首先,JVM的工作原理可以概括为以下几个步骤:编译、加载、验证、准备、解析、初始化和运行。Java源代码被编译成...
Java内存模型(JMM)规定了线程之间的共享变量如何通信和同步。synchronized、volatile、final关键字在其中起到关键作用,确保多线程环境下的正确性。 5. **垃圾收集** JVM自动管理内存,通过垃圾收集器(如...