java內存模型下一些「自然」的先行發生關係,這些先行發生關係無須任何同步器協助就已經存在,能夠在編碼中直接使用。若是兩個操做之間的關係再也不此列,而且沒法從下面規則中推導出來,則它們就沒有順序性保障,虛擬機能夠對它們進行任意地重排序。java
happen-before原則是什麼?
happens-before 口訣:若是兩個操做之間具備happens-before 關係,那麼前一個操做的結果就會對後面一個操做可見。併發
常見的happens-before規則:app
(註解:若是隻有一個線程的操做,那麼前一個操做的結果確定會對後續的操做可見。)編碼
監視器鎖規則:對一個監視器鎖的解鎖,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內存語義。
相信有了這些規則,只有理解他們,咱們就能開發出更好的併發程序。