java-多線程深入(三)happens-before介紹

在多線程中存在可見性問題,詳見 java-多線程深入(二)互斥性和可見性,可見性遵循happens-before規則。

(一)happens-before規則

happens-before規則:若A happens-before B,則操作A中的影響都能被B知道,影響包括修改主內存中共享變量值、發送消息、調用方法等。

java內存模型中的八成happens-before規則:

1、程序次序規則:單線程中,按照程序代碼,前面的操作happens-before後面的操作。

2、鎖定規則:對於同一個鎖,unlock的操作happens-before lock的操作。

3、volatile變量規則:對volatile變量寫操作happens-before讀操作。

4、傳遞性:如果操作A happens—before操作B,操作B happens—before操作C,那麼可以得出A happens—before操作C。
5、線程啓動規則:Thread對象的start方法happens—before此線程的每一個動作。
6、線程終止規則:線程的所有操作都happens—before對此線程的終止檢測,可以通過Thread.join()方法結束、Thread.isAlive()的返回值等手段檢測到線程已經終止執行。
7、線程中斷規則:對線程interrupt方法的調用happens—before發生於被中斷線程的代碼檢測到中斷時事件的發生。
8、對象終結規則:一個對象的初始化完成(構造函數執行結束)happens—before它的finalize方法的開始。


(二)tb和hb的關係

tb(time-before)和hb(happens-before)沒有直接的關係。tb指按照程序執行情況,操作在前的tb操作在後的。

1、tb不代表hb

/**
 * 多線程可見性測試
 * 
 * @author peter_wang
 * @create-time 2015-1-12 下午3:56:29
 */
public class ThreadVisableDemo {
    private static int a = 0;

    static class GetNumThread
        extends Thread {
        @Override
        public void run() {
            System.out.println(a);//B1
        }
    }

    static class ChangeNumThread
        extends Thread {
        @Override
        public void run() {
            a = 1;//A1,A2
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        GetNumThread getNumThread = new GetNumThread();
        ChangeNumThread changeNumThread = new ChangeNumThread();
        changeNumThread.start();//C1
        getNumThread.start();//C2
    }

}
C1先於C2執行,存在C1 tb C2關係,但由上一篇博文可知,a不存在可見性,執行A1完數據不一定會及時刷新,B1最終輸出可爲0或1,C1 hb C2不存在。

2.hb不代表tb

a = 1;  //A1
b = 2;   //A2
按照規則1,A1 hb A2,因爲兩段代碼沒存在數據關聯(A1和A2互換不會影響運行結果),JVM自動優化性能,可能存在編譯代碼重排序或執行指令代碼重排序問題,所以可能存在A2 tb A1。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章