007.多線程-Java內存模型

版權聲明:本文爲博主原創文章,允許轉載,請標明出處。 https://blog.csdn.net/qwdafedv/article/details/84074639

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

  • 保證線程之間的可見性
  • 禁止指令重排序優化

普通的共享變量不能保證可見性,因爲普通的共享變量被修改之後, 什麼時候被寫入主內存是不確定的。 當其他線程去讀取時,此時內存中可能還是原來的舊值,因此無法保證可見性。

當寫一個volatile變量時,JMM會把該線程對應的工作內存中的共享變量值刷新到主內存中, 當讀取一個volatile變量時,JMM會把該線程對應的工作內存置爲無效,那麼該線程將只能從主內存中重新讀取共享變量。

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,
    * 使用該變量對其他線程立即可見,
    * 從而達到線程安全的目的。
    */
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章