java内存模型JSR133
主内存和工作内存
变量存放在主内存,每条线程有自己的工作内存,工作内存保存了使用到的变量的主内存的副本拷贝,线程对变量的所有操作都必须在工作内存进行。通过如下8种操作进行内存间的交互操作:
- lock: 作用于主内存的变量,把一个变量标记为一条线程独占状态。
- unlock
- read: 作用于主内存,将变量从主内存拷出。
- load: 作用于工作内存,将拷出的值写入工作内存。read和load必须配套使用,不允许单独使用。
- use: 作用于工作内存,将值传递给执行引擎。
- assign: 作用于工作内存,把从执行引擎接收到的值付给工作内存。
- store: 作用于工作内存,将变量值拷出。
- write: 作用于主内存,将拷出的值写入主内存。store和write必须配套使用,不允许单独使用。
使用规则
- read和load,store和write不允许单独使用。
- 一个变量如果被assign过,则一定需要同步回主内存。如果没有assign过则不允许同步回主内存。
- lock操作,会清空当前线程中此变量的值,再次从主内存读取。
- unlock操作,会把数据同步回主内存。(store, write)
volatile
volatile具有两个特性(1)保证此变量对所有线程的可见性。写的时候,会将工作内存里面修改过的数据全部同步回主内存。读的时候,会将工作内存设为无效,从主内存重新读取。(2)禁止指令重排,等于在使用该变量的地方建立了内存屏障,屏障后面的语句一定不会提到屏障前面去执行。另外,volatile还保证对double,long变量的load, store, read, write是原子的。(对于现代虚拟机而言,即使不用volatile,也不会读到半个的double,long值。)
原子性、可见性与有序性
原子性: 基本类型的读写是原子的。synchronized块也是原子的。
可见性: 通过volatile,synchronized和final保证。退出同步块时一定会把数据同步回主内存,通过store, write, unlock操作。final字段一旦被初始化完成就是可见的。
有序性: 通过volatile和synchronized保证。