Java volatile
上次修改时间:2024 年 7 月 16 日
在本文中,我们定义了 Java volatile 关键字,并展示了如何使用它。
Java 中的 volatile
关键字是一种变量修饰符,它告诉 Java 虚拟机 (JVM) 一个变量可以被多个线程访问和修改。
volatile
关键字解决了多线程程序中的可见性问题。它确保对变量所做的更改能立即对其他线程可见。
volatile 变量的值始终从主内存读取和写入到主内存。这可以防止线程看到缓存在 CPU 寄存器或缓存中的过期值。这对于多线程编程至关重要,因为多个线程可能同时访问同一个变量。换句话说,它确保每次读取 volatile 变量都直接从计算机的主内存读取(而不是从 CPU 缓存读取),并且每次写入 volatile 变量都写入到主内存(不仅仅是写入到 CPU 寄存器)。
要点
-
volatile
确保其他线程对更改的可见性。 - 它不保证操作的原子性(不可分割性)。
-
volatile
对于标志、计数器或其他只需要可见性的变量非常有用。 - 对于需要可见性和原子性的场景,首选 synchronized 块或方法。
Happens-Before 关系
Java 内存模型 (JMM) 中的一个关键概念是“happens-before”。这定义了所有线程必须看到的操作顺序。 对 volatile 变量的写入建立了与对同一变量的所有后续读取的 happens-before 关系。这意味着在 volatile 写入之前对其他变量所做的任何更改,在写入之后,对读取 volatile 变量的线程变得可见。
标志示例
在下一个示例中,我们有一个 worker,它会一直运行直到标志设置为 false。
class Worker implements Runnable { private volatile boolean isRunning = false; public void setRunning() { isRunning = true; } public void stopTask() { isRunning = false; } public boolean isRunning() { return isRunning; } @Override public void run() { System.out.println("worker started"); while (isRunning) { try { Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("doing task " + System.currentTimeMillis()); } System.out.println(isRunning); System.out.println("worker ended"); } } void main() throws InterruptedException { System.out.println("Main thread started"); final var worker = new Worker(); worker.setRunning(); // Thread to start the task var starter = new Thread(worker); starter.start(); Thread.sleep(2000); // Thread to stop the task using the flag var stopper = new Thread(() -> { if (worker.isRunning()) { worker.stopTask(); System.out.println("stopping task"); } }); stopper.start(); starter.join(); // stopper.join(); System.out.println("Main thread ended"); }
isRunning
标志控制 Worker
类中 run
方法的执行。while 循环持续检查 isRunning
的值。 如果另一个线程修改了 isRunning
的值(例如,通过调用 stopTask
),则该更改将立即对执行循环的线程可见。
如果没有 volatile
,不同的线程可能拥有 isRunning
的自己的本地副本,从而导致数据不一致。
在我们的例子中,只有可见性很重要。 如果我们还需要确保操作的原子性,我们需要选择同步方法或其他工具来代替。
来源
在本文中,我们使用了 Java 中的 volatile
关键字。
作者
列出所有Java教程。