- Java 內存模型

計算機在執行程序的時候,都是CPU在處理指令,在執行指令的時候,會跟數據打交道,數據存放在主存(物理內存)上,CPU的執行速度要比從內存中讀寫數據的速度快的多,所以每次操作內存都會消耗好多時間,最終會降低CPU的執行效率;

爲了解決這個問題,就在CPU和內存之間增加了一個高速緩存;緩存讀寫數據的操作要比主存快得多;

使用高效緩存之後,程序運行時,會先將運算需要的數據從主存複製一份到高效緩存中,CPU運行計算時,就可以直接從緩存中獲取數據和向緩存中寫入數據,運算結束後,再將高效緩存中的數據刷新到主存中;

隨着CPU能力的不斷提升,一層緩存慢慢就不能滿足需求了,就加入二級緩存,甚至是三級緩存;

使用多級緩存之後,CPU要讀取數據,就先在一級緩存中找,一級中沒有,再去二級緩存中找,若緩存中都找不到,就到主存中去找;

單核CPU有一套L1、L2、L3緩存,若CPU有多個內核,那每個核心都有一套L1、L2緩存,共享L3緩存;

在這裏插入圖片描述

(1)單核CPU、單線程:緩存只有一個線程訪問,緩存獨佔,不會有訪問衝突問題;

(2)單核CPU、多線程:進程中的多個線程訪問進程中的共享數據,CPU將數據從主存中加載到緩存後,不同線程訪問相同的物理地址的時候,都會映射到相同的緩存位置,這樣即使發生線程切換,緩存仍然不會失效;由於每個時刻都只有一個線程在執行,所以不會有緩存訪問衝突;

(3)多核CPU、多線程:每個核心至少有一個一級緩存,多個線程訪問進程中的共享數據,並且多個線程分別在不同的核心上執行,那每個核心都會有一份主存數據的緩存備份,由於多核可以並行,就會出現多個線程同時寫各自緩存的情況,最後每個緩存之間的數據就可能不同;

所以,在CPU和主存之間增加高效緩存,在多線程場景下,可能存在緩存一致性問題:多核CPU中,每個核心的自己的緩存中,對同一數據的緩存內容可能不一致;

在這裏插入圖片描述

處理器優化和指令重排

(1)在CPU和主存之間增加高效緩存,在多線程場景下會有緩存一致性的問題;

CPU爲了優化程序的執行,可能會進行處理器優化:對代碼亂序執行處理;編程語言的編輯器也會做指令重排;

這樣就會出現新的問題:
(2)處理器優化問題;
(3)編輯器指令重排問題;

併發編程,爲了保證數據的安全,需要滿足3個特性:

  • 原子性:在一個操作中,CPU不可以中途暫停,然後再調度,即不被中斷操作,要不不執行,要不就執行完成;
  • 可見性:多個線程訪問同一個變量時,一個線程修改了變量的值,其他線程能立刻看到修改的值;
  • 有序性:程序的執行順序,按照代碼的先後順序執行;

緩存一致性問題就是可見性問題;
處理器優化會導致原子性問題;
指令重排會導致有序性問題;

內存模型

CPU高效緩存、處理器優化、指令重排導致了上面3個問題;要解決這三個問題,就要用到內存模型;

爲了保證共享內存的原子性、可見性、有序性,內存模型定義了共享內存系統中多線程程序讀寫行爲的規範;通過這些規範來約束對內存的讀寫操作,從而保證指令執行的正確性;

內存模型與處理器有關、與緩存有關、與併發有關、與編譯器也有關。他解決了CPU多級緩存、處理器優化、指令重排等導致的內存訪問問題,保證了併發場景下的一致性、原子性和有序性

Java內存模型(JMM)

內存模型定義了多線程下併發問題的規範,不同語言有不同的實現,Java內存模型就是Java語言對這個內存模型規範的實現;

Java內存模型規定 所有變量都存儲在主存中,每個線程有自己的工作內存,稱爲本地緩存;本地內存保存了該線程中用到的變量數據,它是變量在主存中的拷貝,線程對變量的操作都要在自己的本地內存中進行,不能直接讀寫主存;不同線程之間不能互相訪問對方本地內存中的變量,線程間變量的傳遞都需要自己的工作內存與主存之間進行數據同步;

Java內存模型就作用在主存與線程工作內存之間;它規定了數據什麼時候同步,以及怎麼同步;

在這裏插入圖片描述

JMM是一種規範,目的是解決由於多線程通過共享內存進行通信時,存在的本地內存數據不一致、編譯器會對代碼指令重排序、處理器會對代碼亂序執行等帶來的問題;

Java內存模型的實現

Java提供了一些和併發處理相關的關鍵字:volatile、synchronized、final、concurrent;使用這些關鍵字可以解決多線程併發訪問共享數據帶來的原子性、一致性、有序性問題;

(1)原子性問題:使用synchronized來保證方法和代碼塊內的操作是原子性的;

(2)可見性問題:volatile;
Java內存模型是通過 在變量修改後將新值同步回主內存,在變量讀取前從主存刷新變量值的方式 解決可見性問題的;
volatile關鍵字修飾的變量,在修改後可以立即同步到主存,每次使用前都從主存中刷新;
synchronized、final也可以實現可見性,只是實現方式不同;

(3)有序性問題:volatile、synchronized;

volatile會禁止指令重排,synchronized保證統一時刻只允許有一個線程操作;

整理自:https://blog.csdn.net/hollis_chuang/article/details/80880118

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章