JMM内存模型学习二教程
volatile内存语义
volatile是java虚拟机提供的轻量级的同步机制。volatile可以保证可见性和禁止指令重排。
对被volatile修饰的共享变量总是对所有线程是可见的。当volatile被修饰的共享变量被修改后,修改后的值立马就会被其它线程读到。这就是可见性。
禁止指令重排,保证单个volatile变量的读/写具有原子性。但是对于volatile++
这种复合操作不具有原子
volatile读的内存语义
当写一个volatile变量时,JMM会把该线程工作内存中对应的共享变量刷新到主内存中。
volatile写的内存语义
当读一个volatile变量时,JMM会把该线程工作内存中对应的共享变量副本设置成无效。线程直接从主内存中读取共享变量
voliatile内存语义的实现
前面提到voliatile可以禁止指令重排序和保证可见性,为了保证voliatile内存语义,JMM会分别限制编译器和处理器重排序。这种限制主要是通过内存屏障来实现的。
voliatile重排序规则
是否能重排序第二个操作第一个操作普通读/写voliatile读voliatile写普通读/写否voliatile读否否否voliatile写否否> 总结
第一个操作是voliatile读的时候,不管第二个操作是什么都不能重排序
第二个操作是voliatile写的时候,不管第一个操作是什么都不能重排序
第一个操作是voliatile写的时候,第二个操作是voliatile读的时候不能重排序
内存屏障
为了实现voliatile的内存语义,编译器在生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序:
(1)在每个volatile写操作前面插入一个StoreStore屏障
(2)在每个volatile写操作后面插入一个StoreLoad屏障
(3)在每个volatile读操作后面插入一个LoadLoad屏障
(4)在每个volatile读操作后面插入一个LoadStore屏障
锁的内存语义
锁是Java并发编程中最重要的同步机制。锁除了可以让临界区互斥执行,还可以让释放锁的线程向获取同一个锁的线程发送消息
锁释放的内存语义
当线程释放锁时,JMM会把线程中的工作内存对应的共享变量刷新到主内存中
锁获取的内存语义
当线程获取锁时,JMM会把该线程对应的本地内存置为无效。从而使得被监视器保护的临界区资源必须从主内存中读取共享变量