1. 程式人生 > >007.多執行緒-Java記憶體模型

007.多執行緒-Java記憶體模型

Java記憶體模型 ( Java Memory Model , JMM )

JMM主要是規定了執行緒與記憶體之間的一些關係。

Java記憶體模型中規定,所有的變數都儲存在主記憶體中,
對所有執行緒都是共享的。

而每個執行緒都有自己的工作記憶體。
工作記憶體中儲存的是對主記憶體中某些變數的拷貝。

不同執行緒無法訪問對方的工作記憶體,
執行緒間通訊必須通過主記憶體來完成。

執行緒對所有變數的操作(讀取、賦值等)必須在工作記憶體中進行,
首先,將變數衝主記憶體拷貝到自己的工作記憶體,
然後,對變數進行操作,操作完成後,再將變數更新到主記憶體。


上圖來源於 https://blog.csdn.net/javazejian/article/details/72772461


執行緒安全問題

當多個執行緒同時操作(讀取+賦值)一個數據的時候,
可能因為工作記憶體沒有及時重新整理到主記憶體 (執行緒何時將工作記憶體重新整理到主記憶體是不確定的),
造成執行緒不安全。


多執行緒的三大特性

  • 原子性

    • 原子性指的是一個操作是不可中斷的,即使是在多執行緒環境下,一個操作一旦開始就不會被其他執行緒影響

      int i=1;//原子操作,直接賦值,要麼賦值成功,要麼賦值不成功
      
      i++;//非原子操作,這裡包含了多步:讀取i的值;將i的值加1;將新值賦值給i
      
  • 可見性

    • 當多個執行緒訪問同一個變數時,一個執行緒修改了這個變數的值,其他執行緒能夠立即看得到修改的值。

      解決可見性問題,一般採用volatile
      volatile可以保證可見性,但是卻不能保證原子性
      
      public class VolatileSafe {
      
          volatile boolean close;
      
          public void close(){
              close=true;
          }
      
          public void doWork(){
              while (!close){
                  System.out.println("safe....");
              }
          }
          /**
          * 由於對於boolean變數close值的修改屬於原子性操作,
          * [對於非原子性操作,應使用synchronized關鍵字來保證執行緒安全]
          * 因此可以通過使用volatile修飾變數close,
          * 使用該變數對其他執行緒立即可見,
          * 從而達到執行緒安全的目的。
          */
      }
  • 有序性

    • 程式執行的順序按照程式碼的先後順序執行。

      volatile關鍵字另一個作用就是禁止指令重排優化,
      從而避免多執行緒環境下程式出現亂序執行的現象