中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java并發編程之volatile與JMM多線程內存模型實例分析

發布時間:2022-05-13 10:00:54 來源:億速云 閱讀:97 作者:iii 欄目:開發技術

本篇內容主要講解“Java并發編程之volatile與JMM多線程內存模型實例分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Java并發編程之volatile與JMM多線程內存模型實例分析”吧!

一、通過程序看現象

在開始為大家講解Java 多線程緩存模型之前,我們先看下面的這一段代碼。這段代碼的邏輯很簡單:主線程啟動了兩個子線程,一個線程1、一個線程2。線程1先執行,sleep睡眠2秒鐘之后線程2執行。兩個線程使用到了一個共享變量shareFlag,初始值為false。如果shareFlag一直等于false,線程1將一直處于死循環狀態,所以我們在線程2中將shareFlag設置為true

public class VolatileTest {
  public static boolean shareFlag = false;
  public static void main(String[] args) throws InterruptedException {
    new Thread(() -> {
      System.out.print("開始執行線程1 =>");
      while (!shareFlag){  //shareFlag = false則一直死循環
        //System.out.println("shareFlag=" + shareFlag);
      }
      System.out.print("線程1執行完成 =>");
    }).start();
    Thread.sleep(2000);
    new Thread(() -> {
      System.out.print("開始執行線程2 =>");
      shareFlag = true;
      System.out.print("線程2執行完成 =>");
    }).start();
  }
}

如果你沒有學過JMM線程模型,可能你看完上面的代碼,希望得到的輸出結果是下面這樣的:

開始執行線程1 =>開始執行線程2 =>線程2執行完成 =>線程1執行完成=>

如下圖所示,正常人理解這段代碼,首先執行線程1進入循環,線程2修改shareFlag=true,線程1跳出循環。所以跳出循環的線程1會打印"線程1執行完成=>",但是經過筆者實驗,**"線程1執行完成=>"不會被打印,線程1也沒有跳出死循環**,這是為什么呢?

Java并發編程之volatile與JMM多線程內存模型實例分析

二、為什么會產生這種現象(JMM模型)?

要解釋上面提到的問題,我們就需要學習JMM(Java Memory Model)Java 內存模型,筆者覺得叫做Java多線程內存模型更準確一些。

Java并發編程之volatile與JMM多線程內存模型實例分析

  • 首先,在JMM中每個線程有自己的工作內存,在程序啟動的時候,線程將共享變量加載(read&load)到自己的工作內存中,加載到線程工作內存中的內存變量是主內存中共享變量的副本。也就是說此時shareFlag在內存中有三個副本,值都等于false。

  • 當線程2執行shareFlag=true的時候將其工作內存副本修改為shareFlag=true,同時將副本的值同步寫回(store&write)到主內存中。

  • 但是線程1的工作內存中的shareFlag=false沒有發生變化,所以線程1一直處于死循環之中

三、MESI 緩存一致性協議

按照上文的實驗以及JMM模型,線程2修改的共享變量的值,線程1感知不到。那怎么樣才能讓線程1感知到共享變量的值發生了變化呢?其實也很簡單,給shareFlag共享變量加上volatile關鍵字就可以了。

public volatile static boolean shareFlag = false;

其底層原理是這樣的,加上volatile關鍵字提示JMM遵循MESI 緩存一致性協議,該協議包含如下的緩存使用規范(看不懂可以不看,下文會用簡單的語言及例子描述一下)。

  1. Modified:代表當前Cache行的數據是修改過的(Dirty),并且只在當前CPU的Cache中是修改過的;此時該Cache行的數據與其他Cache中的數據不同,與內存中該行的數據也不同。

  2. Exclusive:代表當前Cache行的數據是有效數據,其他CPU的Cache中沒有這行數據;并且當前Cache行數據與內存中的數據相同。

  3. Shared:代表多個CPU的Cache中都會緩存有這行數據,并且Cache中的數據與內存中的數據一致;

  4. Invalid:表示當前Cache行中的數據無效;

Java并發編程之volatile與JMM多線程內存模型實例分析

上文中的緩存使用規范可能過于復雜,簡單的說就是

  • 當線程2修改shareFlag的時候(參考Modify),告知bus總線我修改了共享變量shareFlag,

  • 線程1對Bus總線進行監聽,當它獲知共享變量shareFlag發生了修改就會將自己工作內存中的shareFlag副本刪除使其失效。

  • 當線程1再次需要使用到shareFlag的時候,發現工作內存中沒有shareFlag變量副本,就會重新從主內存中加載(read&load)

到此,相信大家對“Java并發編程之volatile與JMM多線程內存模型實例分析”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

开平市| 华容县| 克什克腾旗| 皋兰县| 广东省| 仙游县| 澄迈县| 湄潭县| 阳高县| 佛冈县| 临泽县| 固安县| 吕梁市| 连江县| 光泽县| 黄梅县| 绩溪县| 邹平县| 邹城市| 江门市| 翁源县| 明光市| 大安市| 沾化县| 屯留县| 岳普湖县| 咸阳市| 龙山县| 昆山市| 河北区| 新津县| 太和县| 丽江市| 安达市| 得荣县| 大宁县| 鹤峰县| 陕西省| 繁峙县| 静安区| 孟州市|