volatile是jvm的輕量級同步機(jī)制
- 保證可見性
- 不保證原子性
- 禁止指令重排
保證可見性
下屬程序A線程運(yùn)行時(shí)會出現(xiàn)死循環(huán):
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;
}
并不會因?yàn)閒lag的改變而停止淀弹,原因觀察上圖,flag 改變A線程并不知道
加上volatile后,線程A會可見flag的改變饶辙,解決問題
private volatile static boolean flag = true;
不保證原子性
原子性:不可分割,某任務(wù)執(zhí)行,不能被打擾分隔沟绪,要么同時(shí)成功要么同時(shí)失敗
以下實(shí)例的結(jié)果不是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
指令重拍
計(jì)算機(jī)可能不會按照你的寫的那樣運(yùn)行程序: 源代碼 -> 編譯器優(yōu)化重排 -> 內(nèi)存系統(tǒng)也會重排 -> 執(zhí)行空猜。但是 volatile 可以保證指令的順序绽慈,不被重排