JVM連載(2)

JMM Java內(nèi)存模型:

1、 Java的并發(fā)采用“共享內(nèi)存”模型,線程之間通過讀寫內(nèi)存的公共狀態(tài)進(jìn)行通訊。多個(gè)線程之間是不能通過直接傳遞數(shù)據(jù)交互的,它們之間交互只能通過共享變量實(shí)現(xiàn)。
2、 主要目的是定義程序中各個(gè)變量的訪問規(guī)則。
3、 Java內(nèi)存模型規(guī)定所有變量都存儲(chǔ)在主內(nèi)存中,每個(gè)線程還有自己的工作內(nèi)存。
(1) 線程的工作內(nèi)存中保存了被該線程使用到的變量的拷貝(從主內(nèi)存中拷貝過來),線程對(duì)變量的所有操作都必須在工作內(nèi)存中執(zhí)行,而不能直接訪問主內(nèi)存中的變量。
(2) 不同線程之間無法直接訪問對(duì)方工作內(nèi)存的變量,線程間變量值的傳遞都要通過主內(nèi)存來完成。
(3) 主內(nèi)存主要對(duì)應(yīng)Java堆中實(shí)例數(shù)據(jù)部分。工作內(nèi)存對(duì)應(yīng)于虛擬機(jī)棧中部分區(qū)域。

1532709451-5ad313f437a51.png

4、Java線程之間的通信由內(nèi)存模型JMM(Java Memory Model)控制。
(1)JMM決定一個(gè)線程對(duì)變量的寫入何時(shí)對(duì)另一個(gè)線程可見。
(2)線程之間共享變量存儲(chǔ)在主內(nèi)存中
(3)每個(gè)線程有一個(gè)私有的本地內(nèi)存,里面存儲(chǔ)了讀/寫共享變量的副本。
(4)JMM通過控制每個(gè)線程的本地內(nèi)存之間的交互,來為程序員提供內(nèi)存可見性保證。
5、可見性、有序性:
(1)當(dāng)一個(gè)共享變量在多個(gè)本地內(nèi)存中有副本時(shí),如果一個(gè)本地內(nèi)存修改了該變量的副本,其他變量應(yīng)該能夠看到修改后的值,此為可見性。
(2)保證線程的有序執(zhí)行,這個(gè)為有序性。(保證線程安全)
6、內(nèi)存間交互操作:
(1)lock(鎖定):作用于主內(nèi)存的變量,把一個(gè)變量標(biāo)識(shí)為一條線程獨(dú)占狀態(tài)。
(2)unlock(解鎖):作用于主內(nèi)存的變量,把一個(gè)處于鎖定狀態(tài)的變量釋放出來,釋放后的變量才可以被其他線程鎖定。
(3)read(讀取):作用于主內(nèi)存變量,把主內(nèi)存的一個(gè)變量讀取到工作內(nèi)存中。
(4)load(載入):作用于工作內(nèi)存,把read操作讀取到工作內(nèi)存的變量載入到工作內(nèi)存的變量副本中
(5)use(使用):作用于工作內(nèi)存的變量,把工作內(nèi)存中的變量值傳遞給一個(gè)執(zhí)行引擎。
(6)assign(賦值):作用于工作內(nèi)存的變量。把執(zhí)行引擎接收到的值賦值給工作內(nèi)存的變量。
(7)store(存儲(chǔ)):把工作內(nèi)存的變量的值傳遞給主內(nèi)存
(8)write(寫入):把store操作的值入到主內(nèi)存的變量中
6.1、注意:
(1)不允許read、load、store、write操作之一單獨(dú)出現(xiàn)
(2)不允許一個(gè)線程丟棄assgin操作
(3)不允許一個(gè)線程不經(jīng)過assgin操作,就把工作內(nèi)存中的值同步到主內(nèi)存中
(4)一個(gè)新的變量只能在主內(nèi)存中生成
(5)一個(gè)變量同一時(shí)刻只允許一條線程對(duì)其進(jìn)行l(wèi)ock操作。但lock操作可以被同一條線程執(zhí)行多次,只有執(zhí)行相同次數(shù)的unlock操作,變量才會(huì)解鎖
(6)如果對(duì)一個(gè)變量進(jìn)行l(wèi)ock操作,將會(huì)清空工作內(nèi)存中此變量的值,在執(zhí)行引擎使用這個(gè)變量前,需要重新執(zhí)行l(wèi)oad或者assgin操作初始化變量的值。
(7)如果一個(gè)變量沒有被鎖定,不允許對(duì)其執(zhí)行unlock操作,也不允許unlock一個(gè)被其他線程鎖定的變量
(8)對(duì)一個(gè)變量執(zhí)行unlock操作之前,需要將該變量同步回主內(nèi)存中

堆的內(nèi)存劃分:

2948191696-5ad31617eb2bd.png

Java堆的內(nèi)存劃分如圖所示,分別為年輕代、Old Memory(老年代)、Perm(永久代)。其中在Jdk1.8中,永久代被移除,使用MetaSpace代替。
1、新生代:
(1)使用復(fù)制清除算法(Copinng算法),原因是年輕代每次GC都要回收大部分對(duì)象。新生代里面分成一份較大的Eden空間和兩份較小的Survivor空間。每次只使用Eden和其中一塊Survivor空間,然后垃圾回收的時(shí)候,把存活對(duì)象放到未使用的Survivor(劃分出from、to)空間中,清空Eden和剛才使用過的Survivor空間。
(2)分為Eden、Survivor From、Survivor To,比例默認(rèn)為8:1:1
(3)內(nèi)存不足時(shí)發(fā)生Minor GC
2、老年代:
(1)采用標(biāo)記-整理算法(mark-compact),原因是老年代每次GC只會(huì)回收少部分對(duì)象。
3、Perm:用來存儲(chǔ)類的元數(shù)據(jù),也就是方法區(qū)。
(1)Perm的廢除:在jdk1.8中,Perm被替換成MetaSpace,MetaSpace存放在本地內(nèi)存中。原因是永久代進(jìn)場(chǎng)內(nèi)存不夠用,或者發(fā)生內(nèi)存泄漏。
(2)MetaSpace(元空間):元空間的本質(zhì)和永久代類似,都是對(duì)JVM規(guī)范中方法區(qū)的實(shí)現(xiàn)。不過元空間與永久代之間最大的區(qū)別在于:元空間并不在虛擬機(jī)中,而是使用本地內(nèi)存。
4、堆內(nèi)存的劃分在JVM里面的示意圖:


2866120826-5ad3196c98b32.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 工作之余,想總結(jié)一下JVM相關(guān)知識(shí)。 Java運(yùn)行時(shí)數(shù)據(jù)區(qū): Java虛擬機(jī)在執(zhí)行Java程序的過程中會(huì)將其管理的...
    Huang遠(yuǎn)閱讀 687評(píng)論 0 2
  • 一、運(yùn)行時(shí)數(shù)據(jù)區(qū)域 Java虛擬機(jī)管理的內(nèi)存包括幾個(gè)運(yùn)行時(shí)數(shù)據(jù)內(nèi)存:方法區(qū)、虛擬機(jī)棧、本地方法棧、堆、程序計(jì)數(shù)器,...
    luhanlin閱讀 615評(píng)論 0 0
  • java程序執(zhí)行過程 運(yùn)行時(shí)數(shù)據(jù)區(qū)域劃分 線程私有區(qū)域 1. 程序計(jì)數(shù)器: 1.1. 這塊內(nèi)存區(qū)域很小,是當(dāng)前線程...
    萍水相逢_程序員閱讀 538評(píng)論 0 1
  • Java內(nèi)存區(qū)域 Java虛擬機(jī)在運(yùn)行程序時(shí)會(huì)把其自動(dòng)管理的內(nèi)存劃分為以上幾個(gè)區(qū)域,每個(gè)區(qū)域都有的用途以及創(chuàng)建銷毀...
    架構(gòu)師springboot閱讀 1,944評(píng)論 0 5
  • 《致迎春花》 好喜歡你純真的模樣 不大不小 不驕不媚 明亮而不耀眼 開了又開 笑臉盈盈 《致小花》 我不知你是桃還...
    青言倩語閱讀 393評(píng)論 0 6

友情鏈接更多精彩內(nèi)容