synchronize
- 既保证原子性又保证可见性
- 由于同时只能有一个线程能执行代码所以能具有原子性
- 底层使用 monnitorenter monintorexit jvm指令实现原子性
- 可见性 synchronizez在线程解锁前,必须把共享变量刷新到主内存,在线程加锁时把自己工作内存的共享变量的值清空重新获取
- 可以重入,在获取锁之后不需要重新获取锁执行
volatile
- 只保证可见性
- 底层使用内存屏障和禁止重排序来保证数据可见性
- 更加轻量级
Java通过几种原子操作完成工作内存和主内存的交互:
lock:作用于主内存,把变量标识为线程独占状态。
unlock:作用于主内存,解除独占状态。
read:作用主内存,把一个变量的值从主内存传输到线程的工作内存。
load:作用于工作内存,把read操作传过来的变量值放入工作内存的变量副本中。
use:作用工作内存,把工作内存当中的一个变量值传给执行引擎。
assign:作用工作内存,把一个从执行引擎接收到的值赋值给工作内存的变量。
store:作用于工作内存的变量,把工作内存的一个变量的值传送到主内存中。
write:作用于主内存的变量,把store操作传来的变量的值放入主内存的变量中。
volatile保持可见性
volatile的规则
read,load,use的动作必须连续出现
assign,store,write动作必须连续出现