版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、基于jvm原理jmm模型和cpu緩存模型深入理解java并發(fā)編程許多以java多線(xiàn)程開(kāi)發(fā)為主題的技術(shù)書(shū)籍,都會(huì)把對(duì)java虛擬機(jī)和java內(nèi)存模型的講解,作為講授java并發(fā)編程開(kāi)發(fā)的主要內(nèi)容,有的還深化到計(jì)算機(jī)系統(tǒng)的內(nèi)存、cpu、緩存等予以解釋。事實(shí)上,在實(shí)際的java開(kāi)發(fā)工作中,僅僅了解并發(fā)編程的創(chuàng)建、啟動(dòng)、管理和通信等基本學(xué)問(wèn)還是不夠的。一方面,假如要開(kāi)發(fā)出高效、平安的并發(fā)程序,就必需深化java內(nèi)存模型和java虛擬機(jī)的工作原理,從底層了解并發(fā)編程的實(shí)質(zhì);更進(jìn)一步地,在現(xiàn)今大數(shù)據(jù)的時(shí)代,要開(kāi)發(fā)出高并發(fā)、高可用、考牢靠的分布式應(yīng)用及各種中間件,更需要深化到計(jì)算機(jī)工作原理的底層去舉行代碼開(kāi)
2、發(fā)。 本文嘗試以一個(gè)較為全面的角度,以java虛擬機(jī)工作原理和java內(nèi)存模型為切入,協(xié)作一些計(jì)算機(jī)cpu緩存的學(xué)問(wèn),深化理解java多線(xiàn)程開(kāi)發(fā)中的難點(diǎn),包括線(xiàn)程平安和線(xiàn)程通信等內(nèi)容。 cpu緩存模型 規(guī)律上來(lái)說(shuō),大部分計(jì)算機(jī)系統(tǒng)的高級(jí)編程語(yǔ)言及其編譯器、虛擬機(jī)等構(gòu)件,都是來(lái)源于計(jì)算機(jī)硬件系統(tǒng)的原理和要求,而不是相反。java虛擬機(jī)和并發(fā)編程原理也不例外,因此第一部分先介紹一下困擾許多初學(xué)者的java多線(xiàn)程開(kāi)發(fā)的源頭——cpu緩存模型。 計(jì)算機(jī)中,全部的計(jì)算都是在cpu寄存器中完成,而命令完成所需要的數(shù)據(jù)讀取和寫(xiě)入,都需要從ram主存獵取。受硬件工藝的影
3、響,現(xiàn)在的cpu處理速度已經(jīng)遠(yuǎn)遠(yuǎn)超過(guò)主存的拜訪(fǎng)速度,差額基本是成千上萬(wàn)的差距。 因此,cpu緩存設(shè)計(jì)應(yīng)運(yùn)而生。如下為cpu緩存架構(gòu)圖和cpu緩存與主存的速度對(duì)照: 用法cpu緩存來(lái)處理數(shù)據(jù)的步驟大致為: 1. 把需要的數(shù)據(jù)從主存復(fù)制一份到cpu緩存中; 2. cpu從緩存中讀取數(shù)據(jù)并計(jì)算; 3. 計(jì)算完成的數(shù)據(jù)刷新到主存中。 緩存全都性問(wèn)題 如上的工作機(jī)制,會(huì)在多線(xiàn)程環(huán)境下導(dǎo)致緩存不全都的問(wèn)題。為此,用法總線(xiàn)加鎖(已淘汰)和緩存全都性協(xié)議來(lái)解決,它大致的思想是: 當(dāng)cpu操作緩存中的數(shù)據(jù)時(shí),假如發(fā)覺(jué)該變量是一個(gè)分享變量,意味著其它緩存中也會(huì)有這個(gè)變量的副本,然后—&
4、mdash; 1. 假如是讀操作,不做任何處理,只是從緩存中讀取數(shù)據(jù)到寄存器 2. 假如是寫(xiě)操作,發(fā)出信號(hào)通知其它c(diǎn)pu將該變量的cache line置為無(wú)效狀態(tài),其它c(diǎn)pu在運(yùn)行該變量讀取的時(shí)候需要從主存更新數(shù)據(jù)。 java虛擬機(jī) 受許多資料和書(shū)籍?dāng)⑹霾粐?yán)謹(jǐn)所致,無(wú)數(shù)初學(xué)者往往容易地把java虛擬機(jī)理解為類(lèi)似編譯器甚至說(shuō)明器的存在,把java虛擬機(jī)當(dāng)做黑盒,認(rèn)為輸入了java源代碼,就可以輸出計(jì)算機(jī)挺直跑的程序了;由于jvm在不同操作系統(tǒng)上都有實(shí)現(xiàn),所以可以做到一份代碼,多種機(jī)器運(yùn)行的效果。這樣理解對(duì)小白或者外行人來(lái)說(shuō)可能ok,但對(duì)于有主意深化學(xué)習(xí)java的小伙伴,是遠(yuǎn)遠(yuǎn)不夠的。 實(shí)際上,j
5、ava虛擬機(jī)有自己完美的硬體架構(gòu),如處理器、堆棧、寄存器等,還具有相應(yīng)的命令系統(tǒng)。包括編譯器以及jre在內(nèi)的整套體系,構(gòu)成了完整的jvm。jvm原生支持包括java、scala、kotlin在內(nèi)的語(yǔ)言編譯后運(yùn)行。而其中,jre又是jvm的核心部分。jre的體系結(jié)構(gòu)圖如下: 程序計(jì)數(shù)器:線(xiàn)程私有,每個(gè)線(xiàn)程都有自立的程序計(jì)數(shù)器,用于存放當(dāng)前線(xiàn)程接下來(lái)將要執(zhí)行的字節(jié)碼命令、分支、循環(huán)、跳轉(zhuǎn)、異樣處理等信息。 java虛擬機(jī)棧:線(xiàn)程私有,生命周期與線(xiàn)程相同。線(xiàn)程運(yùn)行中,執(zhí)行辦法時(shí)都會(huì)創(chuàng)建棧幀,用于存放局部變量表、操作棧、動(dòng)態(tài)鏈接、辦法出口等信息。虛擬機(jī)棧的大小可以通過(guò)-xss來(lái)配置,需要特殊注重的是:
6、辦法的調(diào)用是棧幀被壓入和彈出的過(guò)程。在一定的容量之下,假如局部變量表等占用的內(nèi)存越小,則可被壓入的棧幀就越多,反之亦然。棧幀的內(nèi)存大小稱(chēng)為寬度,棧幀的數(shù)量則稱(chēng)為深度,兩者成反比。 本地辦法棧:線(xiàn)程私有,jvm為本地辦法(java native interface, c/c+實(shí)現(xiàn)的程序)所劃分的內(nèi)存區(qū)域,用于被線(xiàn)程調(diào)用諸如網(wǎng)絡(luò)通信、文件操作等辦法。 堆:全部線(xiàn)程分享,java運(yùn)行期間幾乎全部對(duì)象都存儲(chǔ)于此。堆內(nèi)存也會(huì)被細(xì)分為新生代、老生代等子堆。 辦法區(qū):多個(gè)線(xiàn)程分享,存儲(chǔ)那些在類(lèi)的加載階段(詳見(jiàn)下文)已經(jīng)被jvm加載的類(lèi)信息、常量、靜態(tài)變量、即時(shí)編譯器jit編譯后的代碼等數(shù)據(jù)。java8中,改
7、區(qū)的持久代內(nèi)存改為元空間。 特殊地,java程序中線(xiàn)程的數(shù)量,受java虛擬機(jī)棧和堆影響較大,可以粗略地認(rèn)為:一個(gè)java進(jìn)程的內(nèi)存大小=堆內(nèi)存 + 線(xiàn)程數(shù)量 * 線(xiàn)程私有棧內(nèi)存。結(jié)合操作系統(tǒng)特性,可以明確一個(gè)計(jì)算線(xiàn)程數(shù)量的公式:線(xiàn)程數(shù)=(最大地址空間maxprocessmemory - jvm堆內(nèi)存 - 系統(tǒng)保留內(nèi)存reservedosmemory)/threadstacksize(xss) jvm的類(lèi)加載過(guò)程 當(dāng)java源文件經(jīng)過(guò)javac編譯完成,生成類(lèi)文件之后,首先會(huì)被類(lèi)加載器即classloader加載。classloader的主要職責(zé)是加載編譯好的類(lèi)文件,在對(duì)應(yīng)的內(nèi)存區(qū)域中生成該類(lèi)
8、的各個(gè)數(shù)據(jù)結(jié)構(gòu)。類(lèi)的加載分為加載、銜接和初始化三個(gè)階段, 1. 加載:加載類(lèi)的class文件 2. 銜接 2.1 驗(yàn)證:確保class文件的正確性,如版本、魔術(shù)因子等 2.2 預(yù)備:為類(lèi)的靜態(tài)變量分配內(nèi)存,并且初始化默認(rèn)值 2.3 解析:把類(lèi)中的符號(hào)引用轉(zhuǎn)為挺直引用 3. 初始化:為類(lèi)的靜態(tài)變量賦代碼編寫(xiě)階段鎖賦的值 需要注重的是:類(lèi)的加載實(shí)施的是懶加載,即用的時(shí)候才加載,并且在同一個(gè)運(yùn)行時(shí)包下,一個(gè)類(lèi)只會(huì)被初始化一次。 類(lèi)的完整的生命周期,除了類(lèi)加載,還包括用法和卸載。 關(guān)于用法,jvm定義了6種主動(dòng)用法類(lèi)的場(chǎng)景,會(huì)導(dǎo)致類(lèi)的加載和初始化 new對(duì)象;拜訪(fǎng)類(lèi)的靜態(tài)變量(靜態(tài)常量不會(huì)!);拜訪(fǎng)類(lèi)
9、的靜態(tài)辦法;用法反射;初始化子類(lèi)會(huì)初始化父類(lèi);啟動(dòng)類(lèi) 注重初始化一個(gè)類(lèi)為元素的數(shù)組不會(huì)加載類(lèi)。 類(lèi)加載的終于產(chǎn)物,是堆內(nèi)存中的class對(duì)象。而對(duì)于同一個(gè)classloader,不管類(lèi)被加載多少次,指向的都是同一個(gè)class對(duì)象 類(lèi)被加載后在棧內(nèi)存中的分布狀況 java內(nèi)存模型 通過(guò)cpu緩存和jvm工作模式的介紹,是為了引入java內(nèi)存模型的概念。java內(nèi)存模型(java memory mode, jmm)定義了jvm如何與計(jì)算機(jī)的主存舉行工作,理解jmm對(duì)正確理解java多線(xiàn)程開(kāi)發(fā)是非常重要的。jmm模型如下圖所示: java內(nèi)存模型的工作規(guī)律,與上面介紹到的cpu緩存全都性工作規(guī)律非常
10、相像,其關(guān)于多線(xiàn)程的工作要點(diǎn)如下: 1. 分享變量存儲(chǔ)于主內(nèi)存中,每個(gè)線(xiàn)程都可以拜訪(fǎng)。 2. 每個(gè)線(xiàn)程都有私有的工作內(nèi)存,或稱(chēng)本地內(nèi)存。這只是個(gè)規(guī)律概念,其實(shí)質(zhì)是涵蓋了寄存器、緩存、編譯器優(yōu)化和硬件等。 3. 分享變量只以副本的形式,存儲(chǔ)在本地內(nèi)存中。 4. 線(xiàn)程不能挺直操作主內(nèi)存,惟獨(dú)操作了本地內(nèi)存中的副本,才干刷新到主內(nèi)存中。 5. 每個(gè)線(xiàn)程也不能操作其它線(xiàn)程的私有的本地內(nèi)存 java線(xiàn)程平安的實(shí)現(xiàn) java并發(fā)編程平安需要具備的三大特性:原子性、可見(jiàn)性和有序性。下面將介紹,基于jmm模型和java線(xiàn)程平安的實(shí)現(xiàn)方式,是如何確保三大特性的。 原子性 在java并發(fā)編程中,容易的讀取和賦值操
11、作是原子性的,但是多個(gè)原子操作并在一起就不是了,比如將一個(gè)變量賦值給另外一個(gè)變量的操作。 jmm只保證了容易讀取和賦值的原子性。因此,并發(fā)編程中需要用到synchronized實(shí)現(xiàn)同步,或者用法lock接口的實(shí)現(xiàn)類(lèi)加鎖;對(duì)于基本數(shù)據(jù)類(lèi)型如int的自增操作,也可以用法juc包下的java.util.concurrent.atomic.*包下的原子類(lèi)型。而volatile修飾的變量,不具備原子性。 可見(jiàn)性 基于jmm模型,對(duì)于線(xiàn)程讀取分享變量:首次只要從主內(nèi)存讀取到工作內(nèi)存,以后都在工作內(nèi)存中讀取即可;對(duì)于修改分享變量,新值先更新在工作內(nèi)存中,再刷新到主存中。但什么時(shí)候刷新是不確定的。因此,jav
12、a并發(fā)編程中,要確保分享變量在多線(xiàn)程中同步更新,可以實(shí)行如下方式: 通過(guò)synchronized關(guān)鍵字同步,可以確保在鎖釋放之前,對(duì)變量的修改刷新到主內(nèi)存中; 通過(guò)lock接口實(shí)現(xiàn)類(lèi)實(shí)現(xiàn)同步,同樣可以在鎖unlock之前,把修改刷新到主內(nèi)存中; 用法volatile關(guān)鍵字,當(dāng)某線(xiàn)程修改了工作內(nèi)存中的分享變量副本,會(huì)挺直刷新主存中的值,并且其它線(xiàn)程會(huì)立即收到本地內(nèi)存中分享變量副本失效的信息,從而準(zhǔn)時(shí)從主內(nèi)存中更新值。 有序性 在jmm模型中,為了充分利用硬件性能,編譯器和命令器有可能會(huì)對(duì)程序命令舉行重排序。單線(xiàn)程下,這不會(huì)有什么問(wèn)題,但多線(xiàn)程下則可能帶來(lái)意想不到的情況。 關(guān)于并發(fā)編程的有序性,jmm基于一套原生happens-before原則,來(lái)確保了多線(xiàn)程下一定程度的有序性。詳細(xì)說(shuō)來(lái): 程序次序規(guī)章:即便發(fā)生了重排序,在一個(gè)線(xiàn)程內(nèi)終于的運(yùn)行結(jié)果會(huì)與程序編寫(xiě)挨次的結(jié)果全都。 鎖定規(guī)章:先unlock再lock。即一個(gè)鎖是鎖定狀態(tài),需要先解鎖才干再加鎖。 volatile規(guī)章:假如一個(gè)線(xiàn)程對(duì)volatile變量讀,另一個(gè)線(xiàn)程對(duì)該變量寫(xiě),那么寫(xiě)操作一定發(fā)生在讀操作之前。 傳遞規(guī)章:假如操作a先于b,b先于c,那么a絕對(duì)先于
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 金融租賃居間合同模板
- 始興縣中醫(yī)院特殊用房設(shè)施設(shè)備采購(gòu)及安裝及醫(yī)療設(shè)備采購(gòu)項(xiàng)目招標(biāo)文件
- 終止合同退款協(xié)議
- 未維修事故車(chē)買(mǎi)賣(mài)合同協(xié)議書(shū)
- 企業(yè)人才培養(yǎng)與發(fā)展作業(yè)指導(dǎo)書(shū)
- 質(zhì)押礦產(chǎn)權(quán)收益權(quán)擔(dān)保協(xié)議書(shū)
- 養(yǎng)雞業(yè)養(yǎng)殖技術(shù)手冊(cè)
- 庫(kù)房轉(zhuǎn)租合同
- 智能倉(cāng)儲(chǔ)標(biāo)準(zhǔn)化管理與供應(yīng)鏈優(yōu)化項(xiàng)目實(shí)踐
- 焊接結(jié)構(gòu)分析與優(yōu)化作業(yè)指導(dǎo)書(shū)
- 校本課程《生活中的化學(xué)》教案
- 寶典三猿金錢(qián)錄
- 安徽凌瑋新材料科技有限公司年產(chǎn)2萬(wàn)噸超細(xì)二氧化硅氣凝膠系列產(chǎn)品項(xiàng)目環(huán)境影響報(bào)告書(shū)
- 聚合物粘彈性
- 建筑工程施工現(xiàn)場(chǎng)安全資料管理規(guī)程解讀
- 華銀鋁項(xiàng)目氧化鋁系統(tǒng)總體投料試車(chē)方案
- 2023年衛(wèi)生院崗位大練兵大比武競(jìng)賽活動(dòng)實(shí)施方案
- 2023年浙江省初中學(xué)生化學(xué)競(jìng)賽初賽試卷
- 遼海版小學(xué)五年級(jí)美術(shù)下冊(cè)全套課件
- 專(zhuān)題7閱讀理解之文化藝術(shù)類(lèi)-備戰(zhàn)205高考英語(yǔ)6年真題分項(xiàng)版精解精析原卷
- 2022年廣東省10月自考藝術(shù)概論00504試題及答案
評(píng)論
0/150
提交評(píng)論