摘要:内存语义的的实现可见性的实现基于的读取,写入两个操作的内存语义。首先,对中内存屏障的介绍内存屏障用于控制特定条件下的重排序和内存可见性问题。在大多数处理器的实现中,这个屏障是个万能屏障,兼具其它三种内存屏障的功能。
volatile,可见性,有序性 volatile的特性
可见性:对一个volatile变量的读,总能获取其他任意线程对该变量最后的写入。
有序性:JMM会限制volatile变量相关的编译器重排序和处理器重排序。
内存语义的的实现volatile写的内存语义:当写入一个volatile变量的时候,JMM将线程工作内存中的该变量的值刷新到主内存。
volatile读的内存语义:当读取一个volatile变量的时候,JMM首先将该线程工作内存中的这个变量设置为无效,迫使该线程重新从主内存获取最新的有效值。
两者结合起来,就实现了,volatile变量的可见性,因为一个线程去读取volatile变量的时候获取的肯定是最新的值。
能否重排序 | - | 第二个操作 | - |
---|---|---|---|
第一个操作 | 普通读/写 | volatile读 | volatile写 |
普通读/写 | NO | ||
volatile读 | NO | NO | NO |
volatile写 | NO | NO |
理解JMM如何实现volatile的两层内存语义的关键是==内存屏障==。volatile的两层内存语义都是使用内存屏障来实现的。
LoadLoad屏障:对于这样的语句Load1; LoadLoad; Load2,在Load2及后续读取操作要读取的数据被访问前,保证Load1要读取的数据被读取完毕。
StoreStore屏障:对于这样的语句Store1; StoreStore; Store2,在Store2及后续写入操作执行前,保证Store1的写入操作对其它处理器可见。
LoadStore屏障:对于这样的语句Load1; LoadStore; Store2,在Store2及后续写入操作被刷出前,保证Load1要读取的数据被读取完毕。
StoreLoad屏障:对于这样的语句Store1; StoreLoad; Load2,在Load2及后续所有读取操作执行前,保证Store1的写入对所有处理器可见。它的开销是四种屏障中最大的。 在大多数处理器的实现中,这个屏障是个万能屏障,兼具其它三种内存屏障的功能。
volatile写操作前面插入一个StoreStore屏障
对比StoreStore屏障的定义,这里的volatile写是那个Store2,该屏障保证在volatile写执行之前,Store1的写入操作对其他处理器可见,那么可以得出,该屏障不仅保证了Store1已经执行完毕(有序性),也保证了可见性。
每个volatile写操作的后面插入一个StoreLoad屏障
对比StoreLoad屏障的定义,这里的volatile写是那个Store1,该屏障也保证了有序性和可见性。其他都是类似的。
每个volatile读操作后面插入一个LoadLoad屏障。
每个volatile读操作后面插入一个LoadStore屏障。
//假设有个volatile变量instance,对其进行写操作 instance = new Singleton();
在X86处理器下看看其对应的汇编代码的一部分:
lock add1 $0*0
lock前缀的指令在多核处理器下引发了两件事:
当前处理器缓存行的数据写回系统内存
使其他处理器缓存行中缓存的该内存地址的数据无效
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/69347.html
摘要:有可能一个线程中的动作相对于另一个线程出现乱序。当实际输出取决于线程交错的结果时,这种情况被称为竞争条件。这里的问题在于代码块不是原子性的,而且实例的变化对别的线程不可见。这种不能同时在多个线程上执行的部分被称为关键部分。 为什么要额外写一篇文章来研究volatile呢?是因为这可能是并发中最令人困惑以及最被误解的结构。我看过不少解释volatile的博客,但是大多数要么不完整,要么难...
摘要:但在多线程环境中就可能出现问题如下面代码线程语句语句线程线程中的语句和语句并没有数据依赖关系,所以可能会进行指令重排序,先去执行语句,而这时线程会以为线程已经执行完而去执行这样就导致程序出错。 经常会听到volatile这个关键字,但没有深入的去了解过它,今天好好的整理一下要谈volatile,我们先谈谈它的老大哥synchronized一.synchronized 并发编程中最重要的...
摘要:文章简介分析的作用以及底层实现原理,这也是大公司喜欢问的问题内容导航的作用什么是可见性源码分析的作用在多线程中,和都起到非常重要的作用,是通过加锁来实现线程的安全性。而的主要作用是在多处理器开发中保证共享变量对于多线程的可见性。 文章简介 分析volatile的作用以及底层实现原理,这也是大公司喜欢问的问题 内容导航 volatile的作用 什么是可见性 volatile源码分析 ...
摘要:内存模型是围绕着在并发过程中如何处理原子性可见性和有序性这个特征来建立的,我们来看下哪些操作实现了这个特性。可见性可见性是指当一个线程修改了共享变量的值,其他线程能够立即得知这个修改。 Java内存模型是围绕着在并发过程中如何处理原子性、可见性和有序性这3个特征来建立的,我们来看下哪些操作实现了这3个特性。 原子性(atomicity): 由Java内存模型来直接保证原子性变量操作包括...
摘要:并发编程关键字解析解析概览内存模型的相关概念并发编程中的三个概念内存模型深入剖析关键字使用关键字的场景内存模型的相关概念缓存一致性问题。事实上,这个规则是用来保证程序在单线程中执行结果的正确性,但无法保证程序在多线程中执行的正确性。 Java并发编程:volatile关键字解析 1、解析概览 内存模型的相关概念 并发编程中的三个概念 Java内存模型 深入剖析volatile关键字 ...
阅读 3094·2021-11-22 09:34
阅读 594·2021-11-22 09:34
阅读 2440·2021-10-08 10:18
阅读 3373·2021-09-22 15:57
阅读 2586·2021-09-22 15:25
阅读 2400·2019-08-30 15:54
阅读 2099·2019-08-30 15:44
阅读 1801·2019-08-29 11:18