Java关键字:volatile
volatile
volatile 是 Java 中用于确保变量的可见性和有序性的关键字。它在多线程编程中非常有用,尤其是在涉及到共享变量的读写操作时。以下是关于 volatile 的一些关键点:
1. 可见性保证
- 当一个线程对 volatile 变量进行写操作后,任何后续对该变量的读操作都将看到最新的值。这是通过禁止CPU缓存和主内存之间的重排序以及强制线程从主内存读取最新数据来实现的。
2. 禁止指令重排
- volatile 变量可以防止编译器和处理器对它们的读写操作进行重排序,这有助于保持程序执行顺序的一致性。
3. 不保证原子性
- 虽然 volatile 提供了可见性和有序性,但它并不提供原子性保证。例如,对于诸如 i++ 这样的复合操作(读-改-写),即使 i 是 volatile 的,也不能保证线程安全。
4. 适用场景
- 主要适用于不需要原子性但需要可见性和/或有序性的场合,如状态标志、双重检查锁定等。
- 对于简单的读写操作,如果使用恰当,它可以作为比锁更轻量级的选择。
示例代码
以下是一个使用 volatile 关键字的例子,展示如何正确地停止一个线程:
import java.util.concurrent.TimeUnit;
public class StoppableTask extends Thread {
private volatile boolean running = true;
public void run() {
while (running) {
// 执行任务
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("task run");
}
System.out.println("线程已停止");
}
public void shutdown() {
this.running = false;
}
public static void main(String[] args) throws InterruptedException {
StoppableTask task = new StoppableTask();
task.start();
Thread.sleep(1000); // 让任务运行一段时间
task.shutdown(); // 请求停止线程
}
}
在这个例子中,volatile 确保了 running 变量的状态改变能够被检测到,并且能及时终止线程,而不会因为缓存导致的延迟使得线程无法正常结束。
注意事项
- 使用 volatile 时应该明确其限制,特别是它不提供原子性保证这一点。
- 在需要保证原子性的情况下,考虑使用 synchronized 块、java.util.concurrent.atomic 包中的类或者其他的同步机制。