在Java中,每个线程都有自己的堆栈,包括它自己可以访问的变量副本。创建线程时,它会将所有可访问变量的值复制到其自己的堆栈中。该volatile
关键字基本上到JVM说:“警告,这个变量可以在另一个线程修改”,或者意味着 该被volatile修饰的变量有可能被多个线程修改其值。
在所有Java版本中,volatile
关键字都保证对变量的读写操作的全局排序即同步。这意味着访问volatile字段的每个线程都将读取变量的当前值,而不是(可能)使用缓存值。
在Java 5或更高版本中,volatile
读取和写入建立了先happens-before(先发生)关系,就像获取和释放互斥锁一样。
使用volatile
可能比锁更快,但在某些情况下不起作用。在Java 5中扩展了volatile有效的各种情况; 特别是,double-checked-locking(双重检查锁定)现在可以正常工作。
volatile关键字对于64位类型(如long和double)也很有用,因为它们是用两个操作operations编写的。如果没有volatile关键字,将面临过时或无效值的风险。
volatile
使用的一个常见示例是作为终止线程的标志。
如果你已经启动了一个线程,并且你希望能够安全地从另一个线程中断它,你可以让线程定期检查一个标志(即停止它,将标志设置为true
)。通过使标志变为volatile,您可以确保检查其值的线程将看到它已设置为true
甚至不必使用synchronized块。例如:
public class Foo extends Thread {
private volatile boolean close = false;
public void run() {
while(!close) {
// do work
}
}
public void close() {
close = true;
// interrupt here if needed
}
}