小編這次要給大家分享的是如何實現Java并發volatile可見性,文章內容豐富,感興趣的小伙伴可以來了解一下,希望大家閱讀完這篇文章之后能夠有所收獲。
普通讀 無法及時獲得 主內存變量
public class volatileTest {
static boolean flag = false;//非volatile變量
public static void main(String[] args) throws Exception {
new Thread(new Runnable() {
@Override
public void run() {
while(!flag){
};
}
}).start();
Thread.sleep(100);
flag = true;
System.out.println("主線程運行完畢");
}
}主線程已經修改了flag為true,但子線程一直不會退出循環,因為子線程一直沒有同步到 主內存中的變量的值。

截圖可見程序一直沒有退出,使用dump threads后:
"Thread-0" #12 prio=5 os_prio=0 tid=0x0000000022d89800 nid=0x168 runnable [0x00000000248df000]
java.lang.Thread.State: RUNNABLE
at volatileTest$1.run(volatileTest.java:10)
at java.lang.Thread.run(Thread.java:745)
volatile讀 及時獲得 主內存變量
public class volatileTest {
static volatile boolean flag = false;//volatile變量
public static void main(String[] args) throws Exception {
new Thread(new Runnable() {
@Override
public void run() {
while(!flag){
};
}
}).start();
Thread.sleep(100);
flag = true;
System.out.println("主線程運行完畢");
}
}加了一個volatile關鍵字,子線程就能檢測到flag的變化了。子線程會退出。
普通讀+sleep
public class volatileTest {
static boolean flag = false;//非volatile變量
public static void main(String[] args) throws Exception {
new Thread(new Runnable() {
@Override
public void run() {
while(!flag){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
};
}
}).start();
Thread.sleep(100);
flag = true;
System.out.println("主線程運行完畢");
}
}加了sleep,子線程會退出。
其實就算變量不是volatile的,JVM也會盡量去保證可見性。最開始的例子,由于CPU一直執行循環,沒有其他時間來獲取 主內存中的變量的最新值,但加了sleep后,CPU就有時間去獲取 主內存中的東西了。
普通讀+同步塊
public class volatileTest {
static boolean flag = false;//非volatile變量
static Object sync = new Object();
public static void main(String[] args) throws Exception {
new Thread(new Runnable() {
@Override
public void run() {
while(!flag){
synchronized (sync) {}//隨便synchronized一個對象
//synchronized (this)也可以
};
}
}).start();
Thread.sleep(100);
flag = true;
System.out.println("主線程運行完畢");
}
}加了同步塊,子線程會退出。
這是因為synchronized具體過程是:
簡單的說,synchronized進入時,會將 主內存中最新的變量,拷貝進 自己線程 的工作內存。synchronized退出時,會把 自己線程的工作內存的變量 弄進 主內存中。
同步塊 遭遇 鎖消除
public class volatileTest {
static boolean flag = false;//非volatile變量
public static void main(String[] args) throws Exception {
new Thread(new Runnable() {
@Override
public void run() {
while(!flag){
synchronized (new Object()){}
};
}
}).start();
Thread.sleep(100);
flag = true;
System.out.println("主線程運行完畢");
}
}子線程不會退出。
原因是:synchronized (new Object()){}中這個Object永遠不可能逃逸到同步塊以外去,所以同步操作其實根本不需要執行了,既然沒有執行同步,那么相當于這里是啥也沒有。
普通讀+System.out.println
public class volatileTest {
static boolean flag = false;
public static void main(String[] args) throws Exception {
new Thread(new Runnable() {
@Override
public void run() {
while(!flag){
System.out.println("子線程running");
};
}
}).start();
Thread.sleep(100);
flag = true;
System.out.println("主線程運行完畢");
}
}加了System.out.println,子線程會退出。
因為out這個PrintStream實例的println實現是:
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}因為它也有同步塊。
看完這篇關于如何實現Java并發volatile可見性的文章,如果覺得文章內容寫得不錯的話,可以把它分享出去給更多人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。