1、volatile 能保证内存可⻅性
运行下面的例子:
package Demo03;
import java.util.Scanner;
public class demo01 {
private static int flag = 0;
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
while (flag == 0) {
}
System.out.println("t1 线程结束");
});
Thread t2 = new Thread(() -> {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入flag的值:");
flag = scanner.nextInt();
});
t2.start();
t1.start();
}
}
运行后 t1线程并未结束 这显然是个bug
原因分析:
一个线程读取,一个线程修改 修改线程修改的值,并没有被读线程读到。
导致内存可见性问题的因素:
缓存:现代处理器为了提高性能,通常会将频繁访问的数据存储在其私有的高速缓存中。当多个线程运行在不同的CPU核心上时,它们可能会读取到各自缓存中的不同版本的数据,而不是主内存中的最新值
即:t1 读的是⾃⼰⼯作内存中的内容. 当t2对flag变量进⾏修改,此时t1感知不到flag的变化
修改代码:添加关键字 volatile:
package Demo03;
import java.util.Scanner;
public class demo01 {
private volatile static int flag = 0;
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
while (flag == 0) {
}
System.out.println("t1 线程结束");
});
Thread t2 = new Thread(() -> {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入flag的值:");
flag = scanner.nextInt();
});
t2.start();
t1.start();
}
}
运行结果:
2、volatile 不保证保证原子性
运行下面例子:
package Demo03;
import java.util.Scanner;
public class demo01 {
private volatile static int count = 0;
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
for (int i = 0; i <50000 ; i++) {
count++;
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i <50000 ; i++) {
count++;
}
});
t2.start();
t1.start();
t1.join();
t2.join();
System.out.println(count);
}
}
运行结果不能保证原子性