volatile变量
volatile变量是一种同步的弱形式。它确保对一个变量的更新以可预见的方式告知其他的线程。当一个域声明为volatile类型后,编译器与运行时会监视这个变量:它是共享的,而且对它的操作不会与其他的内存操作一起被重排序。volatile变量不会缓存在寄存器或者缓存在对其他处理器隐藏的地方。所以,读一个volatile类型的变量时,总会返回由某一线程所写入的最新值。
volatile变量对可见性的影响所产生的价值远远高于变量本身,线程A向volatile变量写入值,随后线程B读取该变量,所有A执行写操作前可见的变量的值,在B读取了volatile变量后,成为对B也是可见的,所以从内存可见性的角度来看,写入volatile变量就像退出同步块,读取volatile变量就像进入同步块。依赖volatile变量来控制状态可见性的代码,比使用锁的代码更脆弱,更难以理解。
看一下代码示例:volatile变量的典型应用:检查状态标记,以确定是否退出一个循环。
public class CountingSheep {
volatile boolean asleep;
void tryToSleep() {
while (!asleep)
countSomeSheep();
}
void countSomeSheep() {
// One, two, three...
}
}
volatile变量固然方便,但也存在限制。它们通常被当作标识完成,中断,状态的标记使用。
要特别注意:volatile的语义不足以使自增操作原子化,除非你能保证只有一个线程对变量执行写操作。(原子变量提供了“读-改-写”原子操作的支持,而且常被用作“更优的volatile变量”)。
加锁可以保证可见性与原子性;volatile变量只能保证可见性。
只有满足了下面所有的标准后,你才能使用volatile变量:
1.写入变量时不依赖变量的当前值;或者能够确保只有一个线程修改变量的值;
2.变量不需要与其他的状态变量共同参与不变约束;
3.访问变量时,没有其他的原因需要加锁。