JMM的happens-before法則

java內存模型下一些「自然」的先行發生關係,這些先行發生關係無須任何同步器協助就已經存在,能夠在編碼中直接使用。若是兩個操做之間的關係再也不此列,而且沒法從下面規則中推導出來,則它們就沒有順序性保障,虛擬機能夠對它們進行任意地重排序。java

happen-before原則是什麼?
happens-before 口訣:若是兩個操做之間具備happens-before 關係,那麼前一個操做的結果就會對後面一個操做可見。併發

常見的happens-before規則:app

  1. 程序順序規則:一個線程中的每一個操做,happens- before 於該線程中的任意後續操做。

(註解:若是隻有一個線程的操做,那麼前一個操做的結果確定會對後續的操做可見。)編碼

監視器鎖規則:對一個監視器鎖的解鎖,happens- before 於隨後對這個監視器鎖的加鎖。線程

(註解:這個最多見的就是syncronized 方法 和 syncronized塊)code

3.volatile變量規則:對一個volatile域的寫,happens- before 於任意後續對這個volatile域的讀。排序

int a =0;
 volatile int b = 0;
線程1{
 操做1:a = 1;
//插入一個StoreStore屏障 禁止上面的普通寫與下面的volatile 寫重排序
 操做2:b =2;
}
線程2{
 if (b==2)
//LoadLoad屏障。 禁止上面的volatile 與下面的普通讀重排序
  System.out.println(a);//a的值爲多少呢?
}

由於存在屏障,JVM就不會重排序上述代碼。內存

4.傳遞性:若是A happens- before B,且B happens- before C,那麼A happens- before C。開發

(註解:這個看起來就像單線程順序執行。。。)同步

擴展JVM內存屏障插入策略:
在每一個volatile寫操做的前面插入一個StoreStore屏障。

在每一個volatile寫操做的後面插入一個StoreLoad屏障。

在每一個volatile讀操做的後面插入一個LoadLoad屏障。

在每一個volatile讀操做的後面插入一個LoadStore屏障。

上述內存屏障插入策略很是保守,但它能夠保證在任意處理器平臺,任意的程序中都能獲得正確的volatile內存語義。

相信有了這些規則,只有理解他們,咱們就能開發出更好的併發程序。

相關文章
相關標籤/搜索