之前写了一篇java内存模型的文章,里面涉及了volatile的规则。在这里说下我的理解。
首先java内存模型解决了在不同平台和系统中相同的内存访问效果。其次它又定义了一些规则来解决缓存一致性的问题。其中一条规则就是volatile规则。
一个变量被volatile修饰后,就会多了两个语义:
1、volatile修饰后的变量修改后立即对其他线程可见。
2、volatile修饰的变量不会被指令重排序
注:指令重排序(即使编译器和操作系统层面为了优化代码执行速度可能都会进行指令重排序)
第一个语义能保证可见行。第二个语义能保证有序性。离线程安全就差原子性了。
实现原理:
在深入理解java虚拟机一书中讲到:
在有volatile修饰后的变量生成的汇编代码中会出现一个lock前缀。(内存栅栏)
它能保证以下几点
1、在其前面的指令不允许排序到它后面,在它后面的指令不允许重排序到其前面
2、修改后要立即刷新会主内存
3、对主内存的写入操作会使其他缓存失效(高速缓存中的变量不能用了,要用就在取一次)
应用:
由于volatile 只能无法保证原子性。所以volatile使用的时候还是要小心。使用时最好满足下面的条件
1、这次的值与上次没有任何关系(与之相反的就是我这次的值需要通过上次的值根据某种算法算出来)
2、不与其他变量参与对象的不变性条件
像是先判断后执行的操作且判断的条件与上次的值没有关系的时候。就可以用volatile 保证线程安全了。