阅读时间: 10分钟
Volatile关键字 可以确保在应用程式中的可见性,支持变量直接写入到主记忆体(main memory)。
来自《Thinking in Java , edtion 4》的解释
The volatile keyword also ensures visibility across the application. If you declare a field to >be volatile, this means that as soon as a write occurs for that field, all reads will see the >change. This is true even if local caches are involved—volatile fields are immediately written >through to main memory, and reads occur from main memory.
Volatile的主要功能:
第一:提供可见性
当一个变量的前面被加上Volatile后,当它的被修改就会即时被更新到主记忆体(main memory)。
当有其他thread想存取这变量的最新值,都可以在主记忆体(main memory)中看到。
要做到这效果还有其他方法,就是利用Synchronized + Lock来实现。
但不在这里详述,会再另一篇文章作讲解。
public class WorkerThread extends Thread { private boolean isRunning = true; @Override public void run() { while (isRunning) { // execute a task } } public void stopWorker() { isRunning = false; }}
在上面的例子可以看到它有两个tasks分别是run() 和stopWorker() 。
变量isRunning 的预设值true,所以可以执行run() 内的动作。
而stopWorker() 则是可以控制能否执行run() ,因为它可以修改isRunning 的值。
但在这个例子中,即使修改了isRunning 的值为false,run()都仍然有机会执行。
重点在于run()能否在主记忆体中获得最新的isRunning 的值。
为了确保run()能获得最新的isRunning 的值,我们可以利用Volatile关键字来解决。
在变量isRunning前加上volatile:
public class WorkerThread extends Thread { private volatile boolean isRunning = true; @Override public void run() { while (isRunning) { // execute a task } } public void stopWorker() { isRunning = false; }}
第二:保证初始化对象时的次序(happens-before relationship)
public class MyWorker { private int workerNumber; public MyWorker (int workerNumber) { this.workerNumber = workerNumber; } public int getWorkerNumber () { return workerNumber; }}
在上面的例子,我们可以实例化MyWorker class (同时假设这是其中一个Thread,名字叫Thread 1)
MyWorker workerInstance = new MyWorker (1);
当执行之上的code时,JVM 会依以下次序操作:
1: 分配记忆体的空间
2: 将分配到的记忆体的空间(记忆体的空间的地址)给予实例workerInstance
(workerInstance 不再是null了)
3: 将值写入workerInstance
不过在第2个与第3个步骤之间会有机会遇到其他Thread正在执行以下程式:
if(workerInstance!= null){ System.out.println(workerInstance.getValue());}
所以最后由Thread 1实例化MyWorker class的结果不是1。
为了解决上述的问题,我们可以在变量workerNumber前加上volatile关键字。
可以保证JVM只能在完成所有写入程序后(完成第3个步骤后)才能读取workerInstance的值。
public class MyWorker { private volatile int workerNumber; public MyWorker (int workerNumber) { this.workerNumber = workerNumber; } public int getWorkerNumber () { return workerNumber; }}
参考文章/网站/书本:
volatile keywordhttps://www.byteslounge.com/tutorials/java-volatile-example