併發編程系列之volatile內存語義

前言

前面介紹順序一致性模型時,我們提到了程序如果正確的同步就會具備順序一致性,這裏所說的同步泛指廣義上的同步,其中包括就包括同步原語volatile,那麼volatile聲明的變量爲什麼就能保證同步呢?這又是如何實現的呢?今天就讓我們一起來揭開這神祕的面紗,OK,開始我們今天的併發編程之旅吧。

volatile的特性

volatile特性可以理解爲對volatile變量的單個讀寫,看成是使用了同一個鎖對這些單個讀寫進行了同步,他們之間的執行效果是一樣的;volatile變量自身具有下面2種特性:

  • 可見性:對一個volatile變量的讀,總是能看到對這個volatile變量最後的寫入結果,就是保證最後一次的寫入操作一定發生在讀操作之前;

  • 原子性:對任意單個volatile變量的讀-寫具有原子性,但是對於volatile++這種複合操作就不保證其原子性了;

 

volatile寫-讀的內存語義

volatile寫內存語義:當寫一個volatile變量時,JMM會把線程對應的本地內存中的共享變量值刷新到主內存,如下圖所示:

        

volatile讀內存語義:當讀一個volatile變量時,JMM會把線程對應的本地內存置爲無效,線程接下來將從主內存中讀取共享變量,如下圖所示:

          

volatile內存語義的實現

接下來我們再看看volatile在JMM中是如何實現的,首先看下面這張volatile重排序規則表:

NO表示不允許進行重排序,例如當第一個操作是volatile讀時,就不允許重排序,爲了實現volatile內存語義,編譯器在生成字節碼時,會在指令序列中插入內存屏障來禁止特定類型的處理器重排序,下面我們再看看JMM中內存屏障的插入策略:

  • 在每個volatile寫操作的前面插入一個StoreStore屏障。這個屏障可以禁止上面的普通寫和下面的volatile寫發生重排序

  • 在每個volatile寫操作的後面插入一個StoreLoad屏障。該屏障可以防止上面的volatile寫與下面的volatile讀或寫操作發生重排序

  • 在每個volatile讀操作的後面插入一個LoadLoad屏障。該屏障可以禁止下面所有的普通讀操作與上面的volatile讀發生重排序

  • 在每個volatile讀後面插入一個LoadStore屏障,該屏障可以禁止下面所有的普通寫和上面的volatile讀發生重排序

     

volatile寫插入內存屏障後生成的指令序列

volatile讀插入內存屏障後生成的指令序列

 

以上就是同步原語volatile的內存語義,通過這篇文章可以瞭解到底層是如何保證同步的,希望你能有所收穫,感謝閱讀!!!

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