1. 程式人生 > >執行緒的未解之謎

執行緒的未解之謎

簡介:

這是檢驗多執行緒可見性(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這個關鍵字的問題。。。