|
轉(zhuǎn)載自網(wǎng)絡(luò) 現(xiàn)在的計算機,cpu在計算的時候,并不總是從內(nèi)存讀取數(shù)據(jù),它的數(shù)據(jù)讀取順序優(yōu)先級 是:寄存器-高速緩存-內(nèi)存。線程耗費的是CPU,線程計算的時候,原始的數(shù)據(jù)來自內(nèi)存,在計算過程中,有些數(shù)據(jù)可能被頻繁讀取,這些數(shù)據(jù)被存儲在寄存器 和高速緩存中,當線程計算完后,這些緩存的數(shù)據(jù)在適當?shù)臅r候應(yīng)該寫回內(nèi)存。當個多個線程同時讀寫某個內(nèi)存數(shù)據(jù)時,就會產(chǎn)生多線程并發(fā)問題,涉及到三個特 性:原子性,有序性,可見性。在《線程安全總結(jié)》這篇文章中,為了理解方便,我把原子性和有序性統(tǒng)一叫做“多線程執(zhí)行有序性”。支持多線程的平臺都會面臨 這種問題,運行在多線程平臺上支持多線程的語言應(yīng)該提供解決該問題的方案。
那么,我們看看JVM,JVM是一個虛擬 的計算機,它也會面臨多線程并發(fā)問題,java程序運行在java虛擬機平臺上,java程序員不可能直接去控制底層線程對寄存器高速緩存內(nèi)存之間的同 步,那么java從語法層面,應(yīng)該給開發(fā)人員提供一種解決方案,這個方案就是諸如 synchronized, volatile,鎖機制(如同步塊,就緒隊 列,阻塞隊列)等等。這些方案只是語法層面的,但我們要從本質(zhì)上去理解它,不能僅僅知道一個 synchronized 可以保證同步就完了。 在這里我說的是jvm的內(nèi)存模型,是動態(tài)的,面向多線程并發(fā)的,沿襲JSL的“working memory”的說法,只是不想牽扯到太多底層細節(jié),因為 《線程安全總結(jié)》這篇文章意在說明怎樣從語法層面去理解java的線程同步,知道各個關(guān)鍵字的使用場 景。
今天有人問我,那java的線程不是有棧嗎?難道棧不是工作內(nèi)存嗎?工作內(nèi)存這四個字得放到具體的場景 中描述,方能體現(xiàn)它具體的意義,在描述JVM的線程同步時,工作內(nèi)存指的是寄存器和告訴緩存的抽象描述,具體請自行參閱JLS。上面講的都是動態(tài)的內(nèi)存模 型,甚至已經(jīng)超越了JVM的范圍,那么JVM的內(nèi)存靜態(tài)存儲是怎么劃分的?今天還有人問我,jvm的內(nèi)存模型不是有eden區(qū)嗎?也不見你提起。我跟他 說,這是兩個角度去看的,甚至是兩個不同的范圍,動態(tài)的線程同步的內(nèi)存模型,涵蓋了cpu,寄存器,高速緩存,內(nèi)存;JVM的靜態(tài)內(nèi)存儲模型只是一種對內(nèi) 存的物理劃分而已,它只局限在內(nèi)存,而且只局限在JVM的內(nèi)存。那些什么線程棧,eden區(qū)都僅僅在JVM內(nèi)存。
說說JVM的線程棧和有個朋友反復(fù)跟我糾結(jié)的eden區(qū)吧。JVM的內(nèi)存,被劃分了很多的區(qū)域: 1.程序計數(shù)器
關(guān)于垃圾收集,在此不多說,流到垃圾收集那一章再詳細說吧。關(guān)于java的同 步,其實還有基于CPU原語的比較并交換的非阻塞算法(CAS),不過這個在java的并發(fā)包里已經(jīng)實現(xiàn)了很多,因此關(guān)于這點,就留到j(luò)ava并發(fā)包那一 章介紹吧。后面我會專門寫一篇文章,JVM內(nèi)存與垃圾收集。 |
|
|