volatile语义

volatile在Java内存模型(JMM)中,保证共享变量对所有线程可见,但不保证原子性。volatile语义是同步,通过共享变量的方式,完成线程间的通信。
为什么需要volatile
Java内存模型中抽象、简化了计算机物理设备,分成工作内存和主内存,线程有各自的工作内存,却共享主内存。如果要把Java内存模型与物理设备映射起来的话,L1,L2 Cache可以视为工作内存,而L3 Cache视为主内存。线程执行指令时,会优先选择距离 CPU 较近的位置的工作内存中使用,而不会从读写速度较慢的主内存中,我称之为“就近原则”。当线程指令执行完后,赋值给工作内存,如果不回写到主内存,或者通知其他线程,其他线程是无法知晓变量已经修改,仍然会使用曾经缓存在工作内存中的变量,这就造成了缓存不一致的问题,Java使用volatile解决这种问题。volatile保证指令赋值完后的变量立即同步回主内存中,声明并通知其他线程当前赋值的变量已经失效,其他线程在下次使用时会放弃工作内存中变量,使用主内存中的变量。这样就完成了线程间对于volatile修饰的变量的通信。
可见性
执行引擎只与工作内存交互,再有工作内存与主内存交互。站在执行引擎的角度,与工作内存操作完成即表示指令执行完,但是什么时候工作内存会将结果刷新回主内存却不可预测。Java线程间的通信是通过共享内存的方式,线程A如果想通知其他所有线程(线程B,线程C)对于变量f的变化情况,需要满足两点:
- 将变量回写到主内存中
 - 执行引擎读取时强制从主内存中加载
在增加了增加了L1、L2 Cache之后,CPU何时将变量从独享缓存刷新会共享内存,独享缓存是否从共享内存加载变量,时间上都是不可确定的,这就造成了缓存不一致的问题。 
可见性的语义是线程对变量更新操作后,其他线程是可以获知变量的变更情况。
工作内存和主内存关系
原子性
原子操作是一个或多个不可中断的操作,要么一次性完全执行完毕,要么就不执行,最终状态不存在有些操作执行完,有些操作没有执行,在外部看来是不可分割的整体(比如化学中的原子,当然原子也是可以再分割的,不过站在分子层面,原子是最小的不可分割的),原子操作关注的是不被线程调度器中断的操作。
原子性操作是不会出现线程交替执行的情况,如果出现线程交替,则说明操作被线程调度器中断。在Java内存模型中,原子性保证你获取的变量要么是初始值,要么是被某一个线程写入的值,而不会是有多个线程同一时间写入而产生的混乱结果,long或double类型除外(因为变量的前32位可能由一个线程写入,后32位由另一个不同的线程写入),不过加上volatile修饰后的long 和double也具有原子性。
注意:volatile关注可见性,而与原子性没有关系。volatile关注点在于从工作内存刷新回主内存,而原子操作关注的是否不被打断。原子和同步目的都是让不同线程可以安全地访问共享变量的两种处理方式,避免造成内存一致性错误。
我是葛一凡,希望对你有帮助。
参考
- 聊聊并发(一)深入分析Volatile的实现原理
 - 聊聊并发(五)——原子操作的实现原理
 - Java Language Specification
 - Java Volatile 关键字详解
 - 从缓存行出发理解volatile变量、伪共享False sharing、disruptor
 - Java并发编程:volatile关键字解析
 - Java 编程要点之并发(Concurrency)详解
 - Java 并发编程(1): Java 内存模型(JMM)
 
volatile语义的更多相关文章
- 轻量级的同步机制——volatile语义详解(可见性保证+禁止指令重排)
		
目录 1.关于volatile 2.语义一:内存可见性 2.1 一个例子 2.2 java的内存模型(JMM) 2.3 happens-before规则 2.4 volatile解决内存可见性问题的原 ...
 - JAVA锁和volatile的内存语义&volatile的使用场景
		
JAVA锁的内存语义 当线程释放锁时,JMM(Java Memory Model)会把该线程对应的本地内存中的共享变量刷新到主内存中. 当线程获取锁时,JMM会将该线程对应的本地内存置为无效.从而使得 ...
 - Java内存模型-volatile的内存语义
		
一 引言 听说在Java 5之前volatile关键字备受争议,所以本文也不讨论1.5版本之前的volatile.本文主要针对1.5后即JSR-133针对volatile做了强化后的了解. 二 vol ...
 - Java并发编程原理与实战四十二:锁与volatile的内存语义
		
锁与volatile的内存语义 1.锁的内存语义 2.volatile内存语义 3.synchronized内存语义 4.Lock与synchronized的区别 5.ReentrantLock源码实 ...
 - java关键字volatile内存语义详细分析
		
volatile变量自身具有下列特性. 1.可见性.对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写 入. · 2.原子性:对任意单个volatile变量的读/ ...
 - Java的多线程机制系列:不得不提的volatile及指令重排序(happen-before)
		
一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...
 - java并发编程(五)正确使用volatile
		
转载请注明出处: volatile用处说明 在JDK1.2之前,Java的内存模型实现总是从主存(即共享内存)读取变量,是不需要进行特别的注意的.而随着JVM的成熟和优化,现在在多线程 ...
 - Java 理论与实践: 正确使用 Volatile 变量--转
		
原文地址:http://www.ibm.com/developerworks/cn/java/j-jtp06197.html Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 ...
 - Java 理论与实践: 正确使用 Volatile 变量
		
Java 语言中的 volatile 变量可以被看作是一种 "程度较轻的 synchronized":与 synchronized 块相比,volatile 变量所需的编码较少,并 ...
 
随机推荐
- 数据结构习题  线段树&树状数组
			
说明:这是去年写了一半的东西,一直存在草稿箱里,今天整理东西的时候才发现,还是把它发表出来吧.. 以下所有题目来自Lrj的<训练指南> LA 2191 单点修改,区间和 Fenwick直 ...
 - Linux嵌入式 -- 内核 - 内核定时器
			
1. 度量时间差 时钟中断由系统的定时硬件以周期性的时间间隔产生,这个间隔(即频率)由内核根据HZ来确定,HZ是一个与体系结构无关的常数,可配置(50-1200),在X86平台,默认值为1000(每 ...
 - 微服务:Eureka配置集群环境
			
一.注册中心编码 1.使用idea创建一个spring boot项目,pom如下: <?xml version="1.0" encoding="UTF-8" ...
 - MAMP软件的安装和使用
			
MAMP Pro软件是一款很好的在MAC下面运行的网站集成环境软件,功能强大,配置简单,十分便于本地调试,其由Apache+MySQL+PHP+动态DNS配置构成,PHP的版本可以动态切换到最新版.无 ...
 - java关键字---final和transient
			
首先,说说final. final关键字可以修饰变量,方法,类. final变量: 需求: 1 需要一个永不改变的编译时常量 2 ...
 - 理解 JavaScript 对象原型、原型链如何工作、如何向 prototype 属性添加新的方法。
			
JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个原型对象,对象以其原型为模板.从原型继承方法和属性.原型对象也可能拥有原型, ...
 - url字符串中含中文的转码方法
			
凡是用get方法的,url里含中文的,都需要调用上面的函数进行编码.要不然会被当成二进制截断. //URL编码 +(NSString*)urlEncode:(NSString *)str { int ...
 - spring学习-5
			
spring表达式SpEL 语法#{..},为bean的属性进行动态赋值 通过bean的id对bean进行引用 调用方法以及引用对象中的属性 计算表达式的值 正则表达式的匹配 修改Address.ja ...
 - linux进程学习-创建新进程
			
init进程将系统启动后,init将成为此后所有进程的祖先,此后的进程都是直接或间接从init进程“复制”而来.完成该“复制”功能的函数有fork()和clone()等. 一个进程(父进程)调用for ...
 - CODE FESTIVAL 2017 qual A--C - Palindromic Matrix(模拟所有情况,注意细节)
			
个人心得:其实本来这题是有规律的不过当时已经将整个模拟过程都构思出来了,就打算试试,将每个字符和总和用优先队列 装起来,然后枚举每个点,同时进行位置标志,此时需要多少个点的时候拿出最大的和出来,若不满 ...