volatile是jvm的轻量级同步机制
- 保证可见性
- 不保证原子性
- 禁止指令重排
保证可见性
下属程序A线程运行时会出现死循环:
private static boolean flag = true;
public static void main(String[] args) {
Thread A = new Thread(()->{
while (flag){
}
});
A.start();
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag = false;
}
并不会因为flag的改变而停止,原因观察上图,flag 改变A线程并不知道
加上volatile后,线程A会可见flag的改变,解决问题
private volatile static boolean flag = true;
不保证原子性
原子性:不可分割,某任务执行,不能被打扰分隔,要么同时成功要么同时失败
以下实例的结果不是2w, 说明他不保证原子性
private volatile static int number = 0;
public static void main(String[] args) {
for (int i = 0; i < 20; i++) {
new Thread(()->{
for (int j = 0; j < 1000; j++) {
add();
}
}
).start();
}
while (Thread.activeCount()>2){//main gc
Thread.yield();
}
System.out.println(number);
}
public static void add(){
number++;
}
想要保证原子性,可以使用原子类AtomicInteger
number.getAndIncrement() // +1
指令重拍
计算机可能不会按照你的写的那样运行程序: 源代码 -> 编译器优化重排 -> 内存系统也会重排 -> 执行。但是 volatile 可以保证指令的顺序,不被重排