[置顶] java中volatile与原子操作

时间:2022-04-18 00:55:29
在查阅很多资料书后对于java多线程和原子变量之间的关系基本搞明白了。下面一 一讲解。(可能各个版本的虚拟机之间存在差异) 首先,我们来看看volatile关键字。就目前来说,对于volatile关键字的作用也是众说纷纭,其中一种说法是“防止优化编译”。可能很多初学者或者是对计算机的组成原理不太熟悉的同学很难理解这几个字到底所指为何??那么我在这里首先给出一个明确的答案。首先看这样一段代码。
public class Test1 {
private static boolean notify = true;

public static void main(String[] args) throws InterruptedException {
new Thread() {
@Override
public void run() {
while (!notify)
;
System.out.println("这条语句的执行时间与notify有关");
}
}.start();
Thread.sleep(1000);
notify = true;
}

}


很明显,变量notify的值将影响到“System.out.println("这条语句的执行时间与notify有关");”的执行。当我们将notify置为true时,那么该语句将马上得到执行??但事实上远远不是这么简单。线程将notify的值送到寄存器,另一个线程改变了notify的值后,如果此时当前线程的寄存器还长时间保存原来的notify的值,那么while循环依然不会退出。所以所谓的“防止编译优化”就是防止编译器在每次使用的时候没有重新从内存中取值,而是一直使用保存在寄存器中的值。所以,我们将notify标记为volatile型,可以强迫编译器编译的指令每次从内存中取值再判断。这就是所谓的防止编译优化。我们运行这样一段代码:

public class Test1 {
private static int notify = 0;

public static void main(String[] args) throws InterruptedException {
new Thread() {
@Override
public void run() {
while (true)
notify = 1;
}
}.start();
new Thread() {
@Override
public void run() {
while (true)
notify = 2;
}
}.start();
new Thread() {
@Override
public void run() {
while (true)
System.out.println(notify);

}
}.start();
}

}

发现有没有volatile关键字,会对输出1,2变化频率有不小的影响。这正是volatile关键字的作用之一。 下次将介绍volatile关键字对于原子操作的作用。