<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ![](https://cdn.zimug.com/wx-zimug.png) [TOC] ## 一、通過程序看現象 在開始為大家講解Java 多線程緩存模型之前,我們先看下面的這一段代碼。這段代碼的邏輯很簡單:主線程啟動了兩個子線程,一個線程1、一個線程2。線程1先執行,sleep睡眠2秒鐘之后線程2執行。兩個線程使用到了一個共享變量shareFlag,初始值為false。**如果shareFlag一直等于false,線程1將一直處于死循環狀態,所以我們在線程2中將shareFlag設置為true**。 ~~~java 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也沒有跳出死循環**,這是為什么呢? ![](http://cdn.zimug.com/6788aaa12a4cf9691fe566f884347518) ## 二、為什么會產生這種現象(JMM模型)? 要解釋上面提到的問題,我們就需要學習JMM(Java Memory Model)Java 內存模型,筆者覺得叫做Java多線程內存模型更準確一些。 ![](http://cdn.zimug.com/c94e109efa6737c08eec23cb17c3d569) * 首先,在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行中的數據無效; ![](http://cdn.zimug.com/b5ca1efcda9190dc2bdc6e677df7759a) 上文中的緩存使用規范可能過于復雜,簡單的說就是 * 當線程2修改shareFlag的時候(參考Modify),告知bus總線我修改了共享變量shareFlag, * 線程1對Bus總線進行監聽,當它獲知共享變量shareFlag發生了修改就會將自己工作內存中的shareFlag副本刪除使其失效。 * 當線程1再次需要使用到shareFlag的時候,發現工作內存中沒有shareFlag變量副本,就會重新從主內存中加載(read&load)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看