volatile和锁的内存语义与实现
2017-03-28 14:43
127 查看
1.volatile的内存语义与实现
1.1 volatile写读的内存语义
在介绍锁的内存语义之前,我们先简单介绍一下volatile写读的内存语义:当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量值刷新到主内存中。
当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效,线程接下来将从主内存中读取共享变量
这两条保证了volatile能够达到它的即时可见的特性。
那JMM如何能够保证volatile实现其内存语义的,简单来说就是通过内存屏障。如果看过volatile变量汇编后的指令代码就会在代码中发现一句:
lock add1 $0x0
它的简单含义就是要把工作内存中的共享变量值刷新到主内存中,相当于加入内存屏障。
1.2 volatile有序的内存语义
volatile的另一个特性是禁止指令重排序,这里的内存语义我们可以总结为:volatile读之后 的操作不会被重排序到 volatile读之前
volatile写之前 的操作不会被重排序到 volatile写之后
先volatile写–后volatile读,不可重排序
JMM通过插入内存屏障来实现以上语义,实质上有四种内存屏障策略:
volatile写操作前插入StoreStore屏障
volatile写操作后插入StoreLoad屏障
volatile读操作前插入LoadLoad屏障
volatile读操作后插入LoadStore屏障
其中StoreLoad屏障是全能型屏障,可以完成其他3个屏障的功能。所以它被大部分CPU支持。不同CPU有着不同的重排序规则,但是这一套JMM屏障策略可以完成所有类型CPU下的volatile语义。例如对于x86的CPU,它本身只支持写-读操作的重排序,对读-读,读-写,写-写操作的重排序都不支持;那么我们只需要加入StoreLoad屏障来避免写-读操作的重排序即可实现volatile语义。
2.锁的内存语义与实现
理解了volatile的内存语义,锁的内存语义就会好理解了。当线程获取锁时,JMM会把线程对应的本地内存置为无效,然后临界区的代码从主存中读入共享变量到工作内存。
当线程释放锁时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中。
看完上面锁的内存语义,是不是感觉和volatile的内存语义很相像。对比锁和volatile的内存语义:
锁的获取和volatile的读有相同的内存语义
锁的释放和volatile的写有相同的内存语义
那锁的内存语义是如何实现的?
下一篇《ReentrantLock的源代码解析和锁的内存语义实现》将结合jdk源码进行分析。
参考:
特别感谢《Java并发编程的艺术》
http://ifeve.com/volatile/
相关文章推荐
- volatile内存语义以及实现(一)
- 深度解析Java中volatile的内存语义实现以及运用场景
- volatile、内存屏障、Acquire&Release语义 三者的差别和关系(一) —— 之volatile
- volatile的内存语义
- Java内存模型--(四)volatile的内存语义
- java并发编程,volatile内存实现和原理
- volatile、内存屏障、Acquire&Release语义 三者的差别和关系(一) —— 之volatile
- ReentrantLock的源代码解析和锁的内存语义实现
- Java并发编程之九:实现内存可见性的两种方法比较:synchronized和Volatile
- 内存屏障和 volatile 语义
- volatile特性和内存语义
- JMM——volatile的内存语义
- Java之多线程内存可见性_2(volatile实现可见性)
- Java并发编程系列之三:锁与volatile的内存语义
- (读书笔记)volatile内存语义
- [置顶] volatile、内存屏障、Acquire&Release语义 三者的差别和关系(二) —— 之内存屏障
- 【Java并发编程】之十五:并发编程中实现内存可见的两种方法比较:加锁和volatile变量
- 【java多线程系列】java中的volatile的内存语义
- Java实现内存可见性的两种方法比较:synchronized 和 Volatile以及涉及到锁的剖析
- 【Java并发编程】之十五:并发编程中实现内存可见的两种方法比较:加锁和volatile变量