1. volatile 关键字的理解
被 volatile 修饰的变量具有以下两点特性:
- 保证了不同线程对该变量操作的内存可见性
- 禁止指令重排
2. volatile如何保证内存可见性
- 当写一个volatitle变量时,JMM会把该线程对应的本地内存中的共享变量刷新到主存中
- 当读一个volatile变量时,JMM会将线程的本地内存置为无效,然后去主存中进行读取
3. volatile保证可见性,有序性,为啥不能保证一致性
- 保证可见性:如上
- 保证有序性:防止指令重排,按程序顺序执行
- 不能保证原子性:两个线程均拿到i的值为10,线程1还未来得及进行修改,线程2将i变为11并写入主存,线程1再将i由10写为11,更新主存,少了1,因为缓存置为无效是在读取的时候,两个线程均读到了10
4. volatile 的底层实现机制
如果把有volatitle和没有volatitle 关键字的代码生成汇编代码会发现,有volatitle关键字的代码会多一个lock前缀指令。
lock前缀指令相当于一个内存屏障,内存屏障提供了以下功能:
- 重排序时不能把后边的指令重排到内存屏障之前的位置
- 使得本CPU的Cache写入内存
- 写入动作也会引起别的CPU或者内核无效化其cache,相当于新写入的值对别的线程可见