volatile 这个关键字,接触最多的场景是单利,单利中对 instance 做修饰,这个词怎么解释?知道看了一个例子,才明白些。并发中,如果两个线程不停的对一个成员变量赋值,会产生什么效果呢?
static boolean flag;
static class ThreadA extends Thread {
@Override
public void run() {
while (true) {
if (flag) {
flag = false;
System.out.println("The flag is set false");
}
}
}
}
static class ThreadB extends Thread {
@Override
public void run() {
while (true) {
if (!flag) {
flag = true;
System.out.println("The flag is set true");
}
}
}
}
public static void main(String[] args) {
new ThreadA().start();
new ThreadB().start();
}
按照我的预想,运行上面的代码,两条子线程应该是依次打印日志,但结果却是
The flag is set true
The flag is set true
The flag is set false
The flag is set false
The flag is set false
The flag is set true
The flag is set true
The flag is set true
The flag is set false
The flag is set false
The flag is set false
The flag is set true
The flag is set true
与预想的不一样,并且居然打印了一点日志后不打印了; 两条子线程都是活着,没有被杀死,但为什么没继续打印日志?原来CPU有一些自己的特点。我们会提到原子性等,比如 int i = 2; i++; 我们会说它不是原子性的,不是线程安全,这里也差不多,由于CPU有间隔执行程序,所以就导致并发中,flag 赋值就被覆盖了。这种情况下, flag 用 volatile 修饰后,再次打印,
The flag is set false
The flag is set false
The flag is set false
The flag is set true
The flag is set true
The flag is set true
The flag is set false
The flag is set false
The flag is set false
The flag is set true
The flag is set true
The flag is set true
The flag is set false
The flag is set false
The flag is set false
The flag is set true
The flag is set true
会一直打印,但也不是依次打印,这点要注意。