Java 內(nèi)存模型(JMM)主要是為了規(guī)定線程和內(nèi)存之間的一些關(guān)系;根據(jù) JMM 的設(shè)計(jì),系統(tǒng)存在一個(gè)主內(nèi)存(Main Memory)和工作內(nèi)存(Work Memory),Java中所有變量都儲(chǔ)存在主內(nèi)存中,對于所有線程都是共享的;每條線程都有自己的工作內(nèi)存,工作內(nèi)存中存儲(chǔ)了該線程已讀、寫共享變量的副本,工作內(nèi)存是 JMM 的一個(gè)抽象概念,主要包括:緩存,寫緩沖區(qū),寄存器以及其他的硬件和編譯器優(yōu)化;線程對所有變量的操作都是在工作內(nèi)存中進(jìn)行的,線程之間無法相互直接訪問,變量傳遞均需要通過主內(nèi)存完成。JMM 示意圖如下:
1)可見性問題
CPU 中運(yùn)行的線程從主內(nèi)存中拷貝共享對象 obj 到它的 CPU 緩存,把對象 obj 的 count 變量改為 2,但這個(gè)變更對運(yùn)行在右邊 CPU 中的線程不可見,因?yàn)檫@個(gè)更改還沒有 flush 到主內(nèi)存中,要解決共享對象可見性這個(gè)問題,可以使用 volatile 或加鎖(如:synchronized),來保證可見性。
2)競爭問題
線程A和線程B共享一個(gè)對象 obj,假設(shè)線程A從主存讀取 Obj.count變量到自己的 CPU 緩存,同時(shí),線程B也讀取了 Obj.count 變量到自己的 CPU 緩存,并且這兩個(gè)線程都對 Obj.count 做了加 1 操作;此時(shí),Obj.count 加 1 操作被執(zhí)行了兩次,不過都在不同的 CPU 緩存中,如果這兩個(gè)加 1 操作是串行執(zhí)行的,那么 Obj.count 變量便會(huì)在原始值上加 2,最終主存中的 Obj.count 的值會(huì)是 3;然而如果是并行操作,不管是線程 A 還是線程 B 先 flush 計(jì)算結(jié)果到主存,最終主內(nèi)存中的 Obj.count 只會(huì)增加 1 次變成 2;可以使用加鎖( 如:synchronized) 解決此問題,來保證一致性。
3)重排序問題
在執(zhí)行程序時(shí),為了提高性能,編譯器和處理器常常會(huì)對指令做重排序。
可以使用 volatile 或加鎖(如:synchronized)來保證有序性。
先看一下結(jié)構(gòu)圖:
從圖中可以看出Java內(nèi)存結(jié)構(gòu)包括五大區(qū)域:堆、方法區(qū)、虛擬機(jī)棧、本地方法棧、程序計(jì)數(shù)器,其中堆、方法區(qū)線程共享,虛擬機(jī)棧、本地方法棧、程序計(jì)數(shù)器線程私有。
1)堆
堆是Java虛擬機(jī)管理的最大一塊內(nèi)存區(qū)域,存放所有對象實(shí)例和數(shù)組,因?yàn)槎汛娣诺膶ο笫蔷€程共享的,所以多線程的時(shí)候需要同步機(jī)制;堆又劃分為:年輕代、老年代、永久代(JDK1.7)/元空間(JDK1.8),元空間與永久代的區(qū)別在于:永久代使用的是虛擬機(jī)內(nèi)存,元空間則采用本地內(nèi)存。
2)虛擬機(jī)棧
虛擬機(jī)棧描述的是線程進(jìn)棧出棧的過程,線程結(jié)束內(nèi)存自動(dòng)釋放,它用來存儲(chǔ)當(dāng)前線程運(yùn)行方法所需要的數(shù)據(jù)、指令、返回地址(即局部變量和正在調(diào)用的方法),方法被調(diào)用時(shí)會(huì)在棧中開辟一塊叫棧幀的空間,方法運(yùn)行在棧幀空間中。
3)本地方法棧
本地方法棧與虛擬機(jī)棧的作用十分相似,區(qū)別是虛擬機(jī)棧執(zhí)行的是Java方法服務(wù),而本地方法棧則為虛擬機(jī)使用 native 方法服務(wù),可能底層調(diào)用的 c 或者 c++ 方法。
4)方法區(qū)
方法區(qū)同堆一樣,是所有線程共享的內(nèi)存區(qū)域,又被稱為非堆,用于存儲(chǔ)已被虛擬機(jī)加載的類信息、常量、靜態(tài)變量等。
5)程序計(jì)數(shù)器
程序計(jì)數(shù)器是一塊很小的內(nèi)存空間,它是線程私有的,可以認(rèn)作是當(dāng)前線程的行號(hào)指示器。
參考:
https://www.jianshu.com/p/8a58d8335270
https://www.jianshu.com/p/de097e7a813a
http://tutorials.jenkov.com/java-concurrency/java-memory-model.html
聯(lián)系客服