<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 12, comments - 8, trackbacks - 0, articles - 5
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

    [轉]JAVA內存模型:happens-before法則

    Posted on 2010-11-18 14:42 楊羅羅 閱讀(1090) 評論(0)  編輯  收藏 所屬分類: java.thread
    JMM規范: 

    The rules for happens-before are: 


    Program order rule. Each action in a thread happens-before every action in that thread that comes later in the program order. 



    Monitor lock rule. An unlock on a monitor lock happens-before every subsequent lock on that same monitor lock. 



    Volatile variable rule. A write to a volatile field happens-before every subsequent read of that same field. 



    Thread start rule. A call to Thread.start on a thread happens-before every action in the started thread. 



    Thread termination rule. Any action in a thread happens-before any other thread detects that thread has terminated, either by successfully return from Thread.join or by Thread.isAlive returning false. 



    Interruption rule. A thread calling interrupt on another thread happens-before the interrupted thread detects the interrupt (either by having InterruptedException tHRown, or invoking isInterrupted or interrupted). 



    Finalizer rule. The end of a constructor for an object happens-before the start of the finalizer for that object. 



    Transitivity. If A happens-before B, and B happens-before C, then A happens-before C. 


    appens-before完整規則:

    (1)同一個線程中的每個Action都happens-before于出現在其后的任何一個Action。

    (2)對一個監視器的解鎖happens-before于每一個后續對同一個監視器的加鎖。

    (3)對volatile字段的寫入操作happens-before于每一個后續的同一個字段的讀操作。

    (4)Thread.start()的調用會happens-before于啟動線程里面的動作。

    (5)Thread中的所有動作都happens-before于其他線程檢查到此線程結束或者Thread.join()中返回或者Thread.isAlive()==false。

    (6)一個線程A調用另一個另一個線程B的interrupt()都happens-before于線程A發現B被A中斷(B拋出異?;蛘逜檢測到B的isInterrupted()或者interrupted())。

    (7)一個對象構造函數的結束happens-before與該對象的finalizer的開始

    (8)如果A動作happens-before于B動作,而B動作happens-before與C動作,那么A動作happens-before于C動作。



    ---------------------------- 


    什么是happens-before? 
    happens-before就是“什么什么一定在什么什么之前運行”,也就是保證順序性。 
    因為CPU是可以不按我們寫代碼的順序執行內存的存取過程的,也就是指令會亂序或并行運行, 
    只有上面的happens-before所規定的情況下,才保證順序性。 
    如: 
    Java代碼 
    1. public class Test {  
    2.   
    3.     private int a = 0;  
    4.   
    5.     private long b = 0;  
    6.   
    7.     public void set() {  
    8.         a = 1;  
    9.         b = -1;  
    10.     }  
    11.   
    12.     public void check() {  
    13.         if (! ((b == 0) || (b == -1 && a == 1))  
    14.             throw new Exception("check Error!");  
    15.     }  
    16. }  

    對于set()方法的執行: 
    1. 編譯器可以重新安排語句的執行順序,這樣b就可以在a之前賦值。如果方法是內嵌的(inline),編譯器還可以把其它語句重新排序。 
    2. 處理器可以改變這些語句的機器指令的執行順序,甚到同時執行這些語句。 
    3. 存儲系統(由于被緩存控制單元控制)也可以重新安排對應存儲單元的寫操作順序,這些寫操作可能與其他計算和存儲操作同時發生。 
    4. 編譯器,處理器和存儲系統都可以把這兩條語句的機器指令交叉執行。 
    例如:在一臺32位的機器上,可以先寫b的高位,然后寫a,最后寫b的低位,(注:b為long類型,在32位的機器上分高低位存儲) 
    5. 編譯器,處理器和存儲系統都可以使對應于變量的存儲單元一直保留著原來的值, 
    以某種方式維護相應的值(例如,在CPU的寄存器中)以保證代碼正常運行,直到下一個check調用才更新。 
    ... 
    在單線程(或同步)的情況下,上面的check()永遠不會報錯, 
    但非同步多線程運行時卻很有可能。 


    并且,多個CPU之間的緩存也不保證實時同步, 
    也就是說你剛給一個變量賦值,另一個線程立即獲取它的值,可能拿到的卻是舊值(或null), 
    因為兩個線程在不同的CPU執行,它們看到的緩存值不一樣, 
    只有在synchronized或volatile或final的性況下才能保證正確性, 
    很多人用synchronized時只記得有lock的功能,而忘記了線程間的可見性問題。 
    如: 
    Java代碼 
    1. public class Test {  
    2.   
    3.     private int n;  
    4.   
    5.     public void set(int n) {  
    6.         this.n = n;  
    7.     }  
    8.   
    9.     public void check() {  
    10.         if (n != n)  
    11.             throw new Exception("check Error!");  
    12.     }  
    13. }  

    check()中的 n != n 好像永遠不會成立,因為他們指向同一個值,但非同步時卻很有可能發生。 

    另外,JMM不保證創建過程的原子性,讀寫并發時,可能看到不完整的對象, 
    這也是為什么單例模式中著名的"雙重檢查成例"方法,在Java中行不通。(但.Net的內存模型保證這一點) 
    當然,在Java中單例的延遲加載可以用另一種方案實現(方案四): 

    方案一:非延遲加載單例類 
    Java代碼 
    1. public class Singleton {  
    2.   
    3.   private Singleton(){}  
    4.   
    5.   private static final Singleton instance = new Singleton();  
    6.   
    7.   public static Singleton getInstance() {  
    8.     return instance;     
    9.   }   
    10. }  


    方案二:簡單的同步延遲加載 
    Java代碼 
    1. public class Singleton {   
    2.   
    3.   private static Singleton instance = null;  
    4.   
    5.   public static synchronized Singleton getInstance() {  
    6.     if (instance == null)  
    7.       instance = new Singleton();  
    8.     return instance;     
    9.   }   
    10.   
    11. }   


    方案三:雙重檢查成例延遲加載 
    目的是避開過多的同步, 
    但在Java中行不通,因為同步塊外面的if (instance == null)可能看到已存在,但不完整的實例。 
    JDK5.0以后版本若instance為volatile則可行 
    Java代碼 
    1. public class Singleton {   
    2.   
    3.   private static Singleton instance = null;  
    4.   
    5.   public static Singleton getInstance() {  
    6.     if (instance == null) {  
    7.         synchronized (Singleton.class) {  
    8.             if (instance == null) {  
    9.                 instance = new Singleton();  
    10.             }  
    11.         }  
    12.     }  
    13.     return instance;     
    14.   }   
    15.   
    16. }   


    方案四:類加載器延遲加載 
    Java代碼 
    1. public class Singleton {   
    2.   
    3.   private static class Holder {  
    4.     static final Singleton instance = new Singleton();  
    5.   }  
    6.   
    7.   public static Singleton getInstance() {  
    8.     return Holder.instance;     
    9.   }   
    10.   
    11. }   

    主站蜘蛛池模板: 亚洲日韩v无码中文字幕| 免费h成人黄漫画嘿咻破解版| 亚洲狠狠婷婷综合久久久久| 午夜肉伦伦影院久久精品免费看国产一区二区三区 | 亚洲热线99精品视频| 在线播放免费人成视频网站| 亚洲AV成人潮喷综合网| 免费一级毛suv好看的国产网站| 亚洲精品中文字幕无码蜜桃| 产传媒61国产免费| 免费人成在线观看网站品爱网日本| 亚洲人成网站色7799| 国产免费无遮挡精品视频| 免费大片av手机看片| 区三区激情福利综合中文字幕在线一区亚洲视频1 | 99热精品在线免费观看| 久久亚洲AV成人无码| 精品国产免费人成电影在线观看| 亚洲人成高清在线播放| 夜夜嘿视频免费看| 一级黄色片免费观看| 亚洲成A∨人片在线观看不卡| 久9热免费精品视频在线观看| 亚洲成人免费在线观看| 日韩免费视频播播| 国产福利电影一区二区三区,免费久久久久久久精 | 日本免费精品一区二区三区| 亚洲中文字幕在线第六区| 久久久久免费精品国产| 亚洲人配人种jizz| 免费在线不卡视频| 青青草无码免费一二三区| 亚洲综合久久一本伊伊区| 亚洲高清偷拍一区二区三区 | 国产又黄又爽又猛的免费视频播放 | 亚洲午夜无码毛片av久久京东热| 免费va人成视频网站全| 一级毛片不卡片免费观看| 亚洲AV电影天堂男人的天堂| 中文字幕日韩亚洲| 国产无人区码卡二卡三卡免费|