執行緒的未解之謎
阿新 • • 發佈:2019-02-11
簡介:
這是檢驗多執行緒可見性(volatile關鍵字)的時候發現的問題。請不要再迴圈中使用System.out.println();
這種程式碼,因為他是被synchronized修飾的,所以沒法用來檢測。有沒有大神能解釋一下,下面這些案例是什麼鬼???請不要說加volatile、synchronized能解決這種情況,這個應該大家都知道。我只想知道為什麼會出現在下面這幾個案例的情況。。。
案例一:
執行時執行緒沒法結束,debug的時候執行緒1就能結束( f = isF中打斷點)???
class mythread_volatile2 implements Runnable {
public boolean isF = true;
@Override
public void run() {
boolean f = isF;
while (f) {
f = isF;
}
System.out.println(Thread.currentThread().getName() + "執行緒結束");
}
}
public class Test_volatile2 {
public static void main(String[] args) throws InterruptedException {
mythread_volatile2 m = new mythread_volatile2();
Thread t1 = new Thread(m, "執行緒1");
t1.start();
Thread.sleep(100);
m.isF = false;
Thread.sleep(2000);
System.out.println("aaaaaa");
}
}
案例二:
將案例一種的迴圈中加入執行緒休眠一秒鐘,然後執行,發現執行緒1就能結束了???
class mythread_volatile2 implements Runnable {
public boolean isF = true;
@Override
public void run() {
boolean f = isF;
while (f) {
f = isF;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + "執行緒結束");
}
}
public class Test_volatile2 {
public static void main(String[] args) throws InterruptedException {
mythread_volatile2 m = new mythread_volatile2();
Thread t1 = new Thread(m, "執行緒1");
t1.start();
Thread.sleep(100);
m.isF = false;
Thread.sleep(2000);
System.out.println("aaaaaa");
}
}
案例三:
可能有些人會說沒有用volatile修飾,執行緒之間本來就是不可見的,那請看一下這個案例,你可以去執行一下。。。如果說一直都是不可見的(也就是說一直都沒有去重新整理主記憶體,或者沒有去讀取最新的主記憶體),那這個案例的最後結果輸出的就是3個100。
class mythread_volatile implements Runnable {
int isF = 0;
public int i = 0;
public int j = 0;
@Override
public void run() {
while (isF <= 100) {
if (Thread.currentThread().getName().equals("執行緒1")) {
i = i + 1;
} else {
j = j + 1;
}
isF = isF + 1;
}
}
}
public class Test_volatile {
public static void main(String[] args) throws InterruptedException {
mythread_volatile m = new mythread_volatile();
Thread t1 = new Thread(m, "執行緒1");
Thread t2 = new Thread(m, "執行緒2");
t1.start();
t2.start();
Thread.sleep(10000);
System.out.println(m.isF + " " + m.i + " " + m.j);
}
}
猜想:
1、可能是主執行緒中的本地記憶體沒有重新整理到主記憶體中,但是debug的時候又能結束,所以這種猜想是不科學的。
2、主執行緒中的本地記憶體重新整理到主記憶體中了,可能是執行緒1讀取的是本地執行緒,沒有去讀取主記憶體,但是在迴圈中加入休眠一秒又能結束執行緒。
3、也可能是while這個關鍵字的問題。。。