概述
Java虚拟机规范中试图定义一种Java内存模型(JMM)来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果。
经过长时间的验证和修订,在JDK 1.5(实现了JSR-133)发布后,Java内存模型已经成熟和完善起来了。
主内存与工作内存
Java内存模型规定了所有的变量都存储在主内存中,每个线程都有自己的工作内存,线程的工作内存中保存了被该线程使用到的变量的主内存副本拷贝,线程对变量的所有操作(读取、赋值等)都必须在工作内存中进行,而不能直接读写主内存中的变量。
不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量值的传递均需要通过主内存来完成。
volatile
变量定义为volatile之后,具备两种特性:
- 保证此变量对所有线程的可见性,当一条线程修改了这个变量的值,新值对于其他线程来说是可以立即得知的。
- 禁止指令重排序优化,普通的变量仅仅会保证在该方法的执行过程中所有依赖赋值结果的地方都能获取到正确的结果,而不能保证变量赋值操作的顺序与程序代码中的执行顺序一致。
内存屏障(指令重排时不能把后面的指令重排序到内存屏障之前的位置)
volatile变量的运算在并发下是安全的?
volatile变量在各个线程的工作内存中不存在一致性问题(在各个线程的工作内存中,volatile变量也可以存在不一致的情况,但由于每次使用之前都要先刷新,执行引擎看不到不一致的情况,因此可以认为不存在一致性问题),但是java里面的运算并非原子操作(i++),导致volatile变量的运算在并发下一样是不安全的。
原子性、可见性与有序性
Java内存模型是围绕着在并发过程中如何处理原子性、可见性和有序性这3个特征来建立的。
- 原子性
- 可见性:可见性是指当一个线程修改了共享变量的值,其他线程能够立即得知这个修改。
- 有序性
参考
- 深入理解Java虚拟机 第2版