Java内存模型
Java内存模型的主要作用是定义了程序中各个变量的访问规则。
程序中所有变量都保存在主内存中,每个线程都有各自的工作线程,线程无法直接操作主内存中的变量。当线程需要操作某个变量时先将其从主内存中拷贝到自己的工作内存,操作完毕在同步到主内存,每个线程无法操作其它线程的工作内存。
内存间交互
主内存和工作内存之间的交互有如下八个步骤:
- lock(锁定):将主内存中的某个变量标记为线程独占状态
- unlock(解锁):取消线程独占状态
- read(读取):将主内存中的变量传输到工作内存
- load(加载):将read得到的变量放到工作内存中的变量副本中
- use(使用):将工作内存中的变量传给执行引擎
- assign(赋值):将执行引擎返回的结果保存到工作内存中的变量副本
- store(保存):将工作内存中的变量传输到主内存中
- write(写入):将store过程的值保存到主内存的变量中
从主内存读取时,read和load一定是顺序执行的;保存到主内存时store和write也是顺序执行(顺序执行非连续执行,read和load中间可插入其他操作)
volatile关键字
volatile关键字是Java中最轻量级的同步机制,volatile关键字主要有以下两个作用:
- 保证线程之间的可见性(无法保证原子性)
- 禁止指令重排
之所以volatile能保证可见性是因为使用volatile修饰的变量每次修改后都会直接同步到主内存,每次使用前会直接从主内存之中读取,因此所有的修改对其他线程都是立即可见的。
由于volatile只保证可见性不保证原子性,因此使用时需满足以下两个条件:
- 对变量的操作不依赖变量当前值
- 改变了没有包含在具有其他变量的不变式中
关于指令重排序可参见美团点评技术团队的《Java内存访问重排序的研究》一文。