版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、基于jvm原理jmm模型和cpu緩存模型深入理解java并發(fā)編程許多以java多線程開發(fā)為主題的技術(shù)書籍,都會把對java虛擬機和java內(nèi)存模型的講解,作為講授java并發(fā)編程開發(fā)的主要內(nèi)容,有的還深化到計算機系統(tǒng)的內(nèi)存、cpu、緩存等予以解釋。事實上,在實際的java開發(fā)工作中,僅僅了解并發(fā)編程的創(chuàng)建、啟動、管理和通信等基本學問還是不夠的。一方面,假如要開發(fā)出高效、平安的并發(fā)程序,就必需深化java內(nèi)存模型和java虛擬機的工作原理,從底層了解并發(fā)編程的實質(zhì);更進一步地,在現(xiàn)今大數(shù)據(jù)的時代,要開發(fā)出高并發(fā)、高可用、考牢靠的分布式應用及各種中間件,更需要深化到計算機工作原理的底層去舉行代碼開
2、發(fā)。 本文嘗試以一個較為全面的角度,以java虛擬機工作原理和java內(nèi)存模型為切入,協(xié)作一些計算機cpu緩存的學問,深化理解java多線程開發(fā)中的難點,包括線程平安和線程通信等內(nèi)容。 cpu緩存模型 規(guī)律上來說,大部分計算機系統(tǒng)的高級編程語言及其編譯器、虛擬機等構(gòu)件,都是來源于計算機硬件系統(tǒng)的原理和要求,而不是相反。java虛擬機和并發(fā)編程原理也不例外,因此第一部分先介紹一下困擾許多初學者的java多線程開發(fā)的源頭——cpu緩存模型。 計算機中,全部的計算都是在cpu寄存器中完成,而命令完成所需要的數(shù)據(jù)讀取和寫入,都需要從ram主存獵取。受硬件工藝的影
3、響,現(xiàn)在的cpu處理速度已經(jīng)遠遠超過主存的拜訪速度,差額基本是成千上萬的差距。 因此,cpu緩存設(shè)計應運而生。如下為cpu緩存架構(gòu)圖和cpu緩存與主存的速度對照: 用法cpu緩存來處理數(shù)據(jù)的步驟大致為: 1. 把需要的數(shù)據(jù)從主存復制一份到cpu緩存中; 2. cpu從緩存中讀取數(shù)據(jù)并計算; 3. 計算完成的數(shù)據(jù)刷新到主存中。 緩存全都性問題 如上的工作機制,會在多線程環(huán)境下導致緩存不全都的問題。為此,用法總線加鎖(已淘汰)和緩存全都性協(xié)議來解決,它大致的思想是: 當cpu操作緩存中的數(shù)據(jù)時,假如發(fā)覺該變量是一個分享變量,意味著其它緩存中也會有這個變量的副本,然后—&
4、mdash; 1. 假如是讀操作,不做任何處理,只是從緩存中讀取數(shù)據(jù)到寄存器 2. 假如是寫操作,發(fā)出信號通知其它cpu將該變量的cache line置為無效狀態(tài),其它cpu在運行該變量讀取的時候需要從主存更新數(shù)據(jù)。 java虛擬機 受許多資料和書籍敘述不嚴謹所致,無數(shù)初學者往往容易地把java虛擬機理解為類似編譯器甚至說明器的存在,把java虛擬機當做黑盒,認為輸入了java源代碼,就可以輸出計算機挺直跑的程序了;由于jvm在不同操作系統(tǒng)上都有實現(xiàn),所以可以做到一份代碼,多種機器運行的效果。這樣理解對小白或者外行人來說可能ok,但對于有主意深化學習java的小伙伴,是遠遠不夠的。 實際上,j
5、ava虛擬機有自己完美的硬體架構(gòu),如處理器、堆棧、寄存器等,還具有相應的命令系統(tǒng)。包括編譯器以及jre在內(nèi)的整套體系,構(gòu)成了完整的jvm。jvm原生支持包括java、scala、kotlin在內(nèi)的語言編譯后運行。而其中,jre又是jvm的核心部分。jre的體系結(jié)構(gòu)圖如下: 程序計數(shù)器:線程私有,每個線程都有自立的程序計數(shù)器,用于存放當前線程接下來將要執(zhí)行的字節(jié)碼命令、分支、循環(huán)、跳轉(zhuǎn)、異樣處理等信息。 java虛擬機棧:線程私有,生命周期與線程相同。線程運行中,執(zhí)行辦法時都會創(chuàng)建棧幀,用于存放局部變量表、操作棧、動態(tài)鏈接、辦法出口等信息。虛擬機棧的大小可以通過-xss來配置,需要特殊注重的是:
6、辦法的調(diào)用是棧幀被壓入和彈出的過程。在一定的容量之下,假如局部變量表等占用的內(nèi)存越小,則可被壓入的棧幀就越多,反之亦然。棧幀的內(nèi)存大小稱為寬度,棧幀的數(shù)量則稱為深度,兩者成反比。 本地辦法棧:線程私有,jvm為本地辦法(java native interface, c/c+實現(xiàn)的程序)所劃分的內(nèi)存區(qū)域,用于被線程調(diào)用諸如網(wǎng)絡通信、文件操作等辦法。 堆:全部線程分享,java運行期間幾乎全部對象都存儲于此。堆內(nèi)存也會被細分為新生代、老生代等子堆。 辦法區(qū):多個線程分享,存儲那些在類的加載階段(詳見下文)已經(jīng)被jvm加載的類信息、常量、靜態(tài)變量、即時編譯器jit編譯后的代碼等數(shù)據(jù)。java8中,改
7、區(qū)的持久代內(nèi)存改為元空間。 特殊地,java程序中線程的數(shù)量,受java虛擬機棧和堆影響較大,可以粗略地認為:一個java進程的內(nèi)存大小=堆內(nèi)存 + 線程數(shù)量 * 線程私有棧內(nèi)存。結(jié)合操作系統(tǒng)特性,可以明確一個計算線程數(shù)量的公式:線程數(shù)=(最大地址空間maxprocessmemory - jvm堆內(nèi)存 - 系統(tǒng)保留內(nèi)存reservedosmemory)/threadstacksize(xss) jvm的類加載過程 當java源文件經(jīng)過javac編譯完成,生成類文件之后,首先會被類加載器即classloader加載。classloader的主要職責是加載編譯好的類文件,在對應的內(nèi)存區(qū)域中生成該類
8、的各個數(shù)據(jù)結(jié)構(gòu)。類的加載分為加載、銜接和初始化三個階段, 1. 加載:加載類的class文件 2. 銜接 2.1 驗證:確保class文件的正確性,如版本、魔術(shù)因子等 2.2 預備:為類的靜態(tài)變量分配內(nèi)存,并且初始化默認值 2.3 解析:把類中的符號引用轉(zhuǎn)為挺直引用 3. 初始化:為類的靜態(tài)變量賦代碼編寫階段鎖賦的值 需要注重的是:類的加載實施的是懶加載,即用的時候才加載,并且在同一個運行時包下,一個類只會被初始化一次。 類的完整的生命周期,除了類加載,還包括用法和卸載。 關(guān)于用法,jvm定義了6種主動用法類的場景,會導致類的加載和初始化 new對象;拜訪類的靜態(tài)變量(靜態(tài)常量不會!);拜訪類
9、的靜態(tài)辦法;用法反射;初始化子類會初始化父類;啟動類 注重初始化一個類為元素的數(shù)組不會加載類。 類加載的終于產(chǎn)物,是堆內(nèi)存中的class對象。而對于同一個classloader,不管類被加載多少次,指向的都是同一個class對象 類被加載后在棧內(nèi)存中的分布狀況 java內(nèi)存模型 通過cpu緩存和jvm工作模式的介紹,是為了引入java內(nèi)存模型的概念。java內(nèi)存模型(java memory mode, jmm)定義了jvm如何與計算機的主存舉行工作,理解jmm對正確理解java多線程開發(fā)是非常重要的。jmm模型如下圖所示: java內(nèi)存模型的工作規(guī)律,與上面介紹到的cpu緩存全都性工作規(guī)律非常
10、相像,其關(guān)于多線程的工作要點如下: 1. 分享變量存儲于主內(nèi)存中,每個線程都可以拜訪。 2. 每個線程都有私有的工作內(nèi)存,或稱本地內(nèi)存。這只是個規(guī)律概念,其實質(zhì)是涵蓋了寄存器、緩存、編譯器優(yōu)化和硬件等。 3. 分享變量只以副本的形式,存儲在本地內(nèi)存中。 4. 線程不能挺直操作主內(nèi)存,惟獨操作了本地內(nèi)存中的副本,才干刷新到主內(nèi)存中。 5. 每個線程也不能操作其它線程的私有的本地內(nèi)存 java線程平安的實現(xiàn) java并發(fā)編程平安需要具備的三大特性:原子性、可見性和有序性。下面將介紹,基于jmm模型和java線程平安的實現(xiàn)方式,是如何確保三大特性的。 原子性 在java并發(fā)編程中,容易的讀取和賦值操
11、作是原子性的,但是多個原子操作并在一起就不是了,比如將一個變量賦值給另外一個變量的操作。 jmm只保證了容易讀取和賦值的原子性。因此,并發(fā)編程中需要用到synchronized實現(xiàn)同步,或者用法lock接口的實現(xiàn)類加鎖;對于基本數(shù)據(jù)類型如int的自增操作,也可以用法juc包下的java.util.concurrent.atomic.*包下的原子類型。而volatile修飾的變量,不具備原子性。 可見性 基于jmm模型,對于線程讀取分享變量:首次只要從主內(nèi)存讀取到工作內(nèi)存,以后都在工作內(nèi)存中讀取即可;對于修改分享變量,新值先更新在工作內(nèi)存中,再刷新到主存中。但什么時候刷新是不確定的。因此,jav
12、a并發(fā)編程中,要確保分享變量在多線程中同步更新,可以實行如下方式: 通過synchronized關(guān)鍵字同步,可以確保在鎖釋放之前,對變量的修改刷新到主內(nèi)存中; 通過lock接口實現(xiàn)類實現(xiàn)同步,同樣可以在鎖unlock之前,把修改刷新到主內(nèi)存中; 用法volatile關(guān)鍵字,當某線程修改了工作內(nèi)存中的分享變量副本,會挺直刷新主存中的值,并且其它線程會立即收到本地內(nèi)存中分享變量副本失效的信息,從而準時從主內(nèi)存中更新值。 有序性 在jmm模型中,為了充分利用硬件性能,編譯器和命令器有可能會對程序命令舉行重排序。單線程下,這不會有什么問題,但多線程下則可能帶來意想不到的情況。 關(guān)于并發(fā)編程的有序性,jmm基于一套原生happens-before原則,來確保了多線程下一定程度的有序性。詳細說來: 程序次序規(guī)章:即便發(fā)生了重排序,在一個線程內(nèi)終于的運行結(jié)果會與程序編寫挨次的結(jié)果全都。 鎖定規(guī)章:先unlock再lock。即一個鎖是鎖定狀態(tài),需要先解鎖才干再加鎖。 volatile規(guī)章:假如一個線程對volatile變量讀,另一個線程對該變量寫,那么寫操作一定發(fā)生在讀操作之前。 傳遞規(guī)章:假如操作a先于b,b先于c,那么a絕對先于
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度餐飲供應鏈炊事員聘用及服務保障合同4篇
- 二零二五年度出國定居子女教育規(guī)劃合同4篇
- 二零二五年度水電安裝與環(huán)保驗收服務合同范本4篇
- 二零二五年度車床安全防護裝置供應合同4篇
- 二零二五年度儲罐租賃及遠程監(jiān)控服務合同4篇
- 二零二五年度出租車行業(yè)安全教育培訓合同3篇
- 二零二五年度智能設(shè)備銷售合同樣本
- 二零二四年度飲品店員勞動合同模板(含職位晉升機制)3篇
- 2025年度環(huán)保項目投資合同補充條款4篇
- 二零二四年度園林景觀施工合同臺賬編制指南3篇
- 江蘇省蘇州市2024-2025學年高三上學期1月期末生物試題(有答案)
- 銷售與銷售目標管理制度
- 人教版(2025新版)七年級下冊英語:寒假課內(nèi)預習重點知識默寫練習
- 2024年食品行業(yè)員工勞動合同標準文本
- 2025年第一次工地開工會議主要議程開工大吉模板
- 全屋整裝售后保修合同模板
- 壁壘加筑未來可期:2024年短保面包行業(yè)白皮書
- 高中生物學科學推理能力測試
- GB/T 44423-2024近紅外腦功能康復評估設(shè)備通用要求
- 2024-2030年中國減肥行業(yè)市場發(fā)展分析及發(fā)展趨勢與投資研究報告
- 運動技能學習
評論
0/150
提交評論