我們都知道語言在編譯和執行過程中會對自身程序進行優化
如下:
public class Test{
private static int INIT_VALUE = 0;
private final static int MAX_VALUE = 5;
public static void main(String[] args) {
new Thread(() -> {
int localValue = INIT_VALUE;
while (localValue < MAX_VALUE){
if(localValue != INIT_VALUE){
System.out.printf("The value update to [%d]",INIT_VALUE);
localValue = INIT_VALUE;
}
}
},"READER").start();
new Thread(() -> {
int localValue = INIT_VALUE;
while(localValue < MAX_VALUE){
System.out.printf("Update the value to [%d] \n", ++localValue);
INIT_VALUE = localValue;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"UPDATER").start();
}
猜猜會輸出什麼:
Update the value to [1]
Update the value to [2]
Update the value to [3]
Update the value to [4]
Update the value to [5]
····
程序掛起
因爲2線程啓動後會更新INIT_VALUE 導致INIT_VALUE 迅速到5.
線程1 拿到的INIT_VALUE值還是0,java會內部優化此性能導致1線程 死循環
如何解決這個問題?確保INIT_VALUE能夠讀和寫分開執行並且能夠讓java忽略對該屬性的優化。就需要用到 volatile
package com.handsome.thread2study.chapter3;
/**
* @author jiangkunli
* @date 2020-07-01 11:47 下午
* @description
*/
public class VolatileTest {
private volatile static int INIT_VALUE = 0;
private final static int MAX_VALUE = 5;
public static void main(String[] args) {
new Thread(() -> {
int localValue = INIT_VALUE;
while (localValue < MAX_VALUE){
if(localValue != INIT_VALUE){
System.out.printf("The value update to [%d]",INIT_VALUE);
localValue = INIT_VALUE;
}
}
},"READER").start();
new Thread(() -> {
int localValue = INIT_VALUE;
while(localValue < MAX_VALUE){
System.out.printf("Update the value to [%d] \n", ++localValue);
INIT_VALUE = localValue;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"UPDATER").start();
}
}
這樣執行會發現 2線程執行+後,1線程隨後就會執行updata操作,有序進行
看懂了嗎?
小結:
其實
volatile關鍵字就是將資源鎖定,同時只有一個操作來佔用源,並且是有序進行。1操作、2操作、3操作、一定不會出現 1操作 1操作無序且重複調用的情況!!