一、概述
Java內存模型是Java語言在多線程並發情況下對於共享變量讀寫(實際是共享變量對應的內存操作)的規范,主要是為了解決多線程可見性、原子性的問題,解決共享變量的多線程操作沖突問題。】
JMM描述了Java程序中各種變量(線程共享變量)的訪問規則,以及在JVM中將變量存儲到內存中讀取出變量這樣的底層細節。所有的變量都存儲在主內存中,每個線程都有自己獨立的工作內存,里面保存該線程使用到的變量的副本(主內存中變量的一份拷貝)
JMM的兩條規定
1、線程對共享變量的所有操作都必須在自己的工作內存中進行,不能直接從主內存中讀寫;
2、不同的線程之間無法直接訪問其他線程工作內存中的變量,線程變量值的傳遞需要通過主內存來完成。
(注:Java內存模型(JMM) 和 JVM 內存模型區別 :https://www.cnblogs.com/Jomini/p/13176653.html)
二、並發編程問題
多線程並發編程會涉及到以下的問題:
1)原子性:指在一個操作中就是cpu不可以在中途暫停然后再調度,既不被中斷操作,要不執行完成,要不就不執行。
2)可見性:指當多個線程訪問同一個變量時,一個線程修改了這個變量的值,其他線程能夠立即看得到修改的值。
3)有序性:程序執行的順序按照代碼的先后順序執行,多線程中為了提高性能,編譯器和處理器的常常會對指令做重排(編譯器優化重排、指令並行重排、內存系統重排)。
三、解決並發編程
1)原子性:Java提供了兩個高級字節碼指令monitorenter和monitorexit,對應的是關鍵字synchronized,使用該關鍵字保證方法和代碼塊內的操作的原子性。
2)可見性:Java中的volatile關鍵字提供了一個功能,那就是被其修飾的變量在被修改后可以立即同步到主內存,被其修飾的變量在每次是用之前都從主內存刷新。因此,可以使用volatile來保證多線程操作時變量的可見性。
除了volatile,Java中的synchronized和final
兩個關鍵字也可以實現可見性,只不過實現方式不同
3)有序性:用volatile關鍵字禁止指令重排,用synchronized關鍵字加鎖。
四、指令重新排序
CPU優化性能
參考:
https://blog.csdn.net/qq_41297896/article/details/89949632
https://blog.csdn.net/zengxiantao1994/article/details/89303290