volatile
是Java中的关键字,用于修饰变量,被volatile
修饰的变量可以确保线程对这个变量的读写都是直接从主内存在中进行的。
我们先来看下面一段代码
public class Volatile {
private boolean ready;
public void setReady(boolean ready) {
this.ready = ready;
}
public boolean getReady() {
return this.ready;
}
public static void main(String[] args) throws Exception {
Volatile volatile1 = new Volatile();
new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException exception) {
exception.printStackTrace();
}
volatile1.setReady(true);
System.out.println("设置ready值为true");
}).start();
new Thread(() -> {
while (!volatile1.getReady()) {
}
System.out.println("检测到ready变成" + volatile1.getReady());
}).start();
}
}
运行这段代码,我们查看控制台,可以看到虽然我们在第一个线程中将ready
值设置成了true
,但是第二个线程中,while
仍然进入了一个死循环。
这是因为在两个线程中,ready
的值被隔离了,所以我们在第一个线程中修改的ready
值在第二个线程中是获取不到的。
这个时候,我们可以给ready
变量加上volatile
关键字进行修饰,修改后代码如下
public class Volatile {
private volatile boolean ready;
public void setReady(boolean ready) {
this.ready = ready;
}
public boolean getReady() {
return this.ready;
}
public static void main(String[] args) throws Exception {
Volatile volatile1 = new Volatile();
new Thread(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException exception) {
exception.printStackTrace();
}
volatile1.setReady(true);
System.out.println("设置ready值为true");
}).start();
new Thread(() -> {
while (!volatile1.getReady()) {
}
System.out.println("检测到ready变成" + volatile1.getReady());
}).start();
}
}
再次运行代码,可以发现第一个线程中的内容正常输出了,这就是volatile
关键字的作用,一个线程中修改被volatile
修饰的变量,另外一个变量能立即看到修改后的值。
volatile
关键字有两个作用:可见性及有序性。
可见性
当一个线程修改了被volatile
修饰的变量的值,其他线程能够立刻看到修改后的值。
这是因为被volatile
修饰的变量不会被缓存到寄存器或其他处理器不可见的地方,因此保证了每次读取volatile
变量都会从住内存中读取最新的值。
有序性
被volatile
修饰的变量的读写具有一定的有序性,也就是禁止了指令重排序优化,这就意味着,在一个线程中,对被volatile
修饰的变量的写操作一定发生在后续对这个变量的读操作之前。
评论 (0)