最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

JVM內(nèi)存模型和Java線程內(nèi)存模型

2022-03-08 16:38 作者:房頂上的鋁皮水塔  | 我要投稿

參考內(nèi)容:京東架構(gòu)師100分鐘帶你重新認(rèn)識(shí)Java內(nèi)存模型!讓你面試無(wú)憂!

本文主要分成以下部分:

  1. 簡(jiǎn)單介紹JVM的內(nèi)存模型,并且簡(jiǎn)要分析Java的Minor gc過(guò)程

  2. 介紹Java 線程內(nèi)存模型,并且從匯編角度的層面了解volatile

以上的內(nèi)容參考自站內(nèi)視頻。

JVM內(nèi)存模型概述

如圖所示,JVM內(nèi)存模型分成堆、虛擬機(jī)、本地方法棧、方法區(qū)、程序計(jì)數(shù)器這幾個(gè)部分。

首先來(lái)看看虛擬機(jī)棧

虛擬機(jī)棧

程序在執(zhí)行過(guò)程中會(huì)產(chǎn)生線程,比如Main線程或者是其他的子線程。對(duì)于一個(gè)線程JVM就會(huì)給他分配一個(gè)虛擬機(jī)棧,同時(shí)每一個(gè)線程都有各自的程序計(jì)數(shù)器。在同一個(gè)線程中會(huì)調(diào)用方法,對(duì)于方法調(diào)用,JVM會(huì)給他分配【棧幀】。棧幀中包括四個(gè)方面:

  • 局部變量表

  • 動(dòng)態(tài)鏈接

  • 操作數(shù)棧

  • 方法出口

局部變量表和操作數(shù)棧:

局部變量表表示創(chuàng)建的的名稱,這些數(shù)字會(huì)被放到操作數(shù)棧中。比如上面圖中的代碼:

iconst_1表示將int類型的常量1放如操作數(shù)棧,然后i_store1表示將操作數(shù)棧中的1出棧,并且放到局部變量1,也就是a處。對(duì)于變量b的操作同理。在進(jìn)行變量c的計(jì)算過(guò)程時(shí),后續(xù)的邏輯會(huì)將局部變量1和2(a和b)中的結(jié)果放入操作數(shù)棧進(jìn)行計(jì)算,最后結(jié)果返回。

動(dòng)態(tài)鏈接:關(guān)聯(lián)符號(hào)引用和內(nèi)存地址

方法出口:和上下文切換有關(guān)

本地方法棧

本地方法棧和虛擬機(jī)棧類似,但是里面放的是本地方法的相關(guān)的變量

方法區(qū)

方法區(qū)中主要放常量,靜態(tài)變量和類信息

new出來(lái)的對(duì)象。在虛擬機(jī)棧中,比如如下的代碼:

user句柄是放在常量表中的,但是new 出來(lái)的對(duì)象放在堆上。同理在方法區(qū)中如果有靜態(tài)變量是引用類型,new出來(lái)的對(duì)象也放在堆上。

堆的劃分

堆空間主要分成以下幾個(gè)部分:Eden,s0,s1,老年代。最開(kāi)始new出來(lái)的對(duì)象放在Eden區(qū),如果當(dāng)Eden區(qū)存放滿時(shí),字節(jié)碼執(zhí)行引擎會(huì)啟動(dòng)一個(gè)線程做minor gc。

minor gc中使用的算法被稱作可達(dá)性算法??蛇_(dá)性算法會(huì)從gc Root對(duì)象開(kāi)始。

gc Root

這部分的對(duì)象指的是靜態(tài)變量,本地方法棧引用的對(duì)象,虛擬機(jī)棧中的局部變量表引用的對(duì)象、方法區(qū)中靜態(tài)屬性引用的對(duì)象、常量引用的對(duì)象。

可達(dá)性算法

算法首先從gc Root出發(fā),從這些節(jié)點(diǎn)向下搜索,走過(guò)的過(guò)程就是引用鏈。如果一個(gè)對(duì)象沒(méi)有任何引用鏈和它相連,那么這個(gè)對(duì)象就是不可達(dá)的。對(duì)于不可達(dá)的對(duì)象存留在Eden區(qū),可達(dá)的對(duì)象會(huì)在s0和s1 survivor區(qū)轉(zhuǎn)移。如果這些對(duì)象的對(duì)象頭中的分代年齡字段大于15,將會(huì)被放在老年區(qū)。

Java線程模型

java線程模型分成兩個(gè)部分,一個(gè)是共享內(nèi)存(主內(nèi)存),一個(gè)是線程中的獨(dú)立的內(nèi)存。這部分的內(nèi)存線程之間不能相互訪問(wèn)。如果同時(shí)有兩個(gè)線程,從主內(nèi)存中復(fù)制了一個(gè)對(duì)象并且進(jìn)行修改,修改完成的結(jié)果不會(huì)立刻存回主內(nèi)存,這就是并發(fā)中常出現(xiàn)的寫錯(cuò)誤的問(wèn)題。

為了解決這個(gè)問(wèn)題,我們通常會(huì)在變量之間加上volatile關(guān)鍵字。

volatile關(guān)鍵字的實(shí)現(xiàn)

volatile主要是解決的線程之間的共享變量的可見(jiàn)性的問(wèn)題,它解決的思路是基于JVM定義的一系列硬件層面的原子操作:

舉兩個(gè)線程為例,在沒(méi)有加volatile之前:

左邊的線程只是對(duì)于一個(gè)變量執(zhí)行了一個(gè)讀取的過(guò)程,右邊的線程除了讀取還做了修改的操作??梢钥吹綇墓ぷ鲀?nèi)存到主內(nèi)存需要經(jīng)歷store操作,然后修改值是經(jīng)歷write操作。正是因?yàn)檫@些操作不是原子操作,才會(huì)出現(xiàn)錯(cuò)誤。

volatile關(guān)鍵字早期的實(shí)現(xiàn)方式是對(duì)于總線加鎖的機(jī)制,操作一個(gè)共享變量的時(shí)候,其他的線程都不能對(duì)緩存了這個(gè)共享變量的地址的緩存。但是這樣的開(kāi)銷比較大。

現(xiàn)在的volatile關(guān)鍵字是基于MESI協(xié)議的。volatile關(guān)鍵字在被修改時(shí),會(huì)立刻會(huì)寫到主內(nèi)存,同時(shí)開(kāi)啟MESI協(xié)議,CPU會(huì)開(kāi)啟總線嗅探機(jī)制,使得自身的變量失效。

JVM內(nèi)存模型和Java線程內(nèi)存模型的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
拉萨市| 肃南| 浦江县| 浮山县| 铁力市| 丰宁| 柳林县| 肃宁县| 汽车| 萨迦县| 怀柔区| 天峻县| 阿勒泰市| 中超| 清涧县| 永昌县| 隆德县| 宁津县| 三都| 肃北| 洛隆县| 本溪| 凤庆县| 德保县| 菏泽市| 兴宁市| 即墨市| 永仁县| 罗江县| 尉氏县| 铁岭市| 弥勒县| 星子县| 敦煌市| 阳山县| 开封县| 五河县| 临武县| 乌拉特中旗| 桃园县| 神农架林区|