Java內(nèi)存模型與JVM (二)


第一步重窟,了解JVM基本概念,基本結(jié)構(gòu)驯耻。

第二步亲族,了解JVM中線程私有區(qū)和公有區(qū)。

第三步可缚,了解線程與Java內(nèi)存模型。

第四步斋枢,了解并發(fā)編程



JVM的基礎(chǔ)概念

JVM的中文名稱叫Java虛擬機(jī)帘靡,它是由軟件技術(shù)模擬出計(jì)算機(jī)運(yùn)行的一個(gè)虛擬的計(jì)算機(jī)。

JVM也充當(dāng)著一個(gè)翻譯官的角色瓤帚,我們編寫出的Java程序描姚,是不能夠被操作系統(tǒng)所直接識(shí)別的涩赢,這時(shí)候JVM的作用就體現(xiàn)出來(lái)了,它負(fù)責(zé)把我們的程序翻譯給系統(tǒng)“聽”轩勘,告訴它我們的程序需要做什么操作筒扒。

我們都知道Java的程序需要經(jīng)過(guò)編譯后,產(chǎn)生.Class文件绊寻,JVM才能識(shí)別并運(yùn)行它花墩,JVM針對(duì)每個(gè)操作系統(tǒng)開發(fā)其對(duì)應(yīng)的解釋器,所以只要其操作系統(tǒng)有對(duì)應(yīng)版本的JVM澄步,那么這份Java編譯后的代碼就能夠運(yùn)行起來(lái)冰蘑,這就是Java能一次編譯,到處運(yùn)行的原因村缸。


JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)



JVM體系結(jié)構(gòu)

總內(nèi)存=堆內(nèi)存(Xmx)+方法區(qū)內(nèi)存(MaxPermSize)+棧內(nèi)存(Xss)*線程數(shù)+直接內(nèi)存(MaxDirectMemorySize,堆外)+虛擬機(jī)內(nèi)存

1祠肥、class文件

虛擬機(jī)并不關(guān)心Class的來(lái)源是什么語(yǔ)言,只要它符合Java class文件格式就可以在Java虛擬機(jī)中運(yùn)行梯皿。使用Java編譯器可以把Java代碼編譯為存儲(chǔ)字節(jié)碼的Class文件仇箱,使用JRuby等其他語(yǔ)言的編譯器一樣可以把程序代碼編譯成Class文件。

2东羹、類裝載器子系統(tǒng)

負(fù)責(zé)查找并裝載Class 文件到內(nèi)存工碾,最終形成可以被虛擬機(jī)直接使用的Java類型。

3百姓、方法區(qū)

在類裝載器加載class文件到內(nèi)存的過(guò)程中渊额,虛擬機(jī)會(huì)提取其中的類型信息,并將這些信息存儲(chǔ)到方法區(qū)垒拢。方法區(qū)用于存儲(chǔ)已被虛擬機(jī)加載的類信息旬迹、常量、靜態(tài)變量求类、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)奔垦。由于所有線程都共享方法區(qū),因此它們對(duì)方法區(qū)數(shù)據(jù)的訪問必須被設(shè)計(jì)為是線程安全的尸疆。

對(duì)于每一個(gè)加載的類型椿猎,會(huì)在方法區(qū)中保存以下信息:

類及其父類的全限定名(java.lang.Object沒有父類)

類的類型(Class or Interface)

訪問修飾符(public, abstract, final)

實(shí)現(xiàn)的接口的全限定名的列表

常量池

字段信息

方法信息

除常量外的靜態(tài)變量

ClassLoader引用

Class引用

對(duì)于每一個(gè)字段,會(huì)在方法區(qū)中保存以下信息(字段聲明順序也會(huì)保存):

字段名

字段的類型

字段的修飾符(public, private , protected, static, final, volatile, transient)

對(duì)于每一個(gè)方法寿弱,會(huì)在方法區(qū)中保存以下信息(方法聲明順序也會(huì)保存):

方法名

方法返回類型(或void)

參數(shù)信息

方法修飾符(public, private, protected , static, final, synchronized, native, abstract)

如果方法不是抽象方法并不是本地方法(Native Method)犯眠,還會(huì)保存以下信息:

方法的字節(jié)碼

本地變量表及操作數(shù)棧的大小

異常表

虛擬機(jī)需要存儲(chǔ)一些數(shù)據(jù),用來(lái)快速地訪問一個(gè)類對(duì)象中的方法症革,一般實(shí)現(xiàn)為一個(gè)方法表筐咧。

方法區(qū)中還有一部分是運(yùn)行時(shí)常量池,主要用來(lái)存儲(chǔ)編譯時(shí)生成的字面量和符號(hào)引用,常量也可以在運(yùn)行時(shí)產(chǎn)生量蕊,如String的intern方法铺罢。

方法區(qū)中也可能存在GC,但虛擬機(jī)規(guī)范對(duì)此不做要求残炮,主要是回收一些常量和卸載一些不用的類型信息韭赘,不過(guò)要卸載一個(gè)類的條件很難達(dá)到,而且些處GC其實(shí)也回收不了多少內(nèi)存势就。

JVM常量池也稱之為運(yùn)行時(shí)常量池泉瞻,它是方法區(qū)(Method Area)的一部分。用于存放編譯期間生成的各種字面量和符號(hào)引用蛋勺。由“用于存放編譯期間生成的各種字面量和符號(hào)引用”這句話可見瓦灶,常量池中存儲(chǔ)的是對(duì)象的引用而不是對(duì)象的本身。

4抱完、

存儲(chǔ)Java程序創(chuàng)建的類實(shí)例贼陶。所有線程共享,因此設(shè)計(jì)程序時(shí)也要考慮到多線程訪問對(duì)象(堆數(shù)據(jù))的同步問題巧娱。堆的存取類型為管道類型碉怔,先進(jìn)先出。

5禁添、Java棧

Java棧是線程私有的撮胧。每當(dāng)啟動(dòng)一個(gè)新線程時(shí),Java虛擬機(jī)都會(huì)為它分配一個(gè)Java棧老翘。Java棧以幀為單位保存線程的運(yùn)行狀態(tài)芹啥。虛擬機(jī)只會(huì)直接對(duì)Java棧執(zhí)行兩種操作:以幀為單位的壓棧或出棧铺峭。當(dāng)線程調(diào)用java方法時(shí)墓怀,虛擬機(jī)壓入一個(gè)新的棧幀到該線程的java棧中。當(dāng)方法返回時(shí)卫键,這個(gè)棧幀被從java棧中彈出并拋棄傀履。一個(gè)棧幀包含一個(gè)java方法的調(diào)用狀態(tài),它存儲(chǔ)有局部變量表莉炉、操作棧钓账、動(dòng)態(tài)鏈接灶壶、方法出口等信息疏魏。

6、程序計(jì)數(shù)器

一個(gè)運(yùn)行中的Java程序胧卤,每當(dāng)啟動(dòng)一個(gè)新線程時(shí)羞福,都會(huì)為這個(gè)新線程創(chuàng)建一個(gè)自己的PC(程序計(jì)數(shù)器)寄存器惕蹄。程序計(jì)數(shù)器的作用可以看做是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器。字節(jié)碼解釋器工作時(shí)就是通過(guò)改變這個(gè)計(jì)數(shù)器的值來(lái)選取下一條需要執(zhí)行的字節(jié)碼指令治专,分支卖陵、循環(huán)、跳轉(zhuǎn)张峰、異常處理泪蔫、線程恢復(fù)等基礎(chǔ)功能都需要依賴這個(gè)計(jì)數(shù)器來(lái)完成。如果線程正在執(zhí)行的是一個(gè)Java方法喘批,這個(gè)計(jì)數(shù)器記錄的是正在執(zhí)行的虛擬機(jī)字節(jié)碼指令的地址撩荣;如果正在執(zhí)行的是Natvie方法,這個(gè)計(jì)數(shù)器值則為空(Undefined)

7饶深、本地方法棧

本地方法棧與虛擬機(jī)棧所發(fā)揮的作用是非常相似的餐曹,其區(qū)別不過(guò)是虛擬機(jī)棧為虛擬機(jī)執(zhí)行Java方法(也就是字節(jié)碼)服務(wù),而本地方法棧則是為虛擬機(jī)使用到的Native方法服務(wù)敌厘。任何本地方法接口都會(huì)使用某種本地方法棧台猴。當(dāng)線程調(diào)用Java方法時(shí),虛擬機(jī)會(huì)創(chuàng)建一個(gè)新的棧幀并壓入Java棧俱两。然而當(dāng)它調(diào)用的是本地方法時(shí)饱狂,虛擬機(jī)會(huì)保持Java棧不變,不再在線程的Java棧中壓入新的幀宪彩,虛擬機(jī)只是簡(jiǎn)單地動(dòng)態(tài)鏈接并直接調(diào)用指定的本地方法休讳。如果某個(gè)虛擬機(jī)實(shí)現(xiàn)的本地方法接口是使用C連接模型的話,那么它的本地方法棧就是C棧

8尿孔、執(zhí)行引擎

負(fù)責(zé)執(zhí)行字節(jié)碼俊柔。方法的字節(jié)碼是由Java虛擬機(jī)的指令序列構(gòu)成的。每一條指令包含一個(gè)單字節(jié)的操作碼活合,后面跟隨0個(gè)或多個(gè)操作數(shù)雏婶。執(zhí)行引擎執(zhí)行字節(jié)碼時(shí),首先取得一個(gè)操作碼芜辕,如果操作碼有操作數(shù)尚骄,取得它的操作數(shù)。它執(zhí)行操作碼和跟隨的操作數(shù)規(guī)定的動(dòng)作侵续,然后再取得下一個(gè)操作碼倔丈。這個(gè)執(zhí)行字節(jié)碼的過(guò)程在線程完成前將一直持續(xù)。


虛擬機(jī)中線程的私有與共享區(qū)

JVM內(nèi)存分為兩個(gè)主要區(qū)域状蜗,一個(gè)是所有線程共享的數(shù)據(jù)區(qū)需五,一個(gè)是線程隔離數(shù)據(jù)區(qū)線程私有。

線程隔離數(shù)據(jù)區(qū)

1轧坎、程序計(jì)數(shù)器(Program?Counter?Register):

一小塊內(nèi)存空間宏邮,單前線程所執(zhí)行的字節(jié)碼行號(hào)指示器。字節(jié)碼解釋器工作時(shí),通過(guò)改變這個(gè)計(jì)數(shù)器的值來(lái)選取下一條需要執(zhí)行的字節(jié)碼指令蜜氨,分支械筛、循環(huán)、跳轉(zhuǎn)飒炎、異常處理埋哟、線程恢復(fù)等基礎(chǔ)功能都需要依賴這個(gè)計(jì)數(shù)器來(lái)完成。

2郎汪、JVM虛擬機(jī)棧(Java?Virtual?Machine?Stacks):

Java方法執(zhí)行內(nèi)存模型赤赊,用于存儲(chǔ)局部變量,操作數(shù)棧煞赢,動(dòng)態(tài)鏈接抛计,方法出口等信息。是線程私有的照筑。

3吹截、本地方法棧(Native?Method?Stacks):

為JVM用到的Native方法服務(wù),Sun?HotSpot?虛擬機(jī)把本地方法棧和JVM虛擬機(jī)棧合二為一朦肘。是線程私有的饭弓。

線程共享的數(shù)據(jù)區(qū)

1、方法區(qū)Method?Area):

用于存儲(chǔ)JVM加載的類信息媒抠、常量弟断、靜態(tài)變量、即使編譯器編譯后的代碼等數(shù)據(jù)趴生。

2阀趴、運(yùn)行時(shí)常量池Runtime?Constant?Pool):

是方法區(qū)的一部分,用于存放編譯器生成的各種字面量和符號(hào)引用苍匆,這部分內(nèi)容將在類加載后存放到方法取得運(yùn)行時(shí)常量池中刘急。具備動(dòng)態(tài)性,用的比較多的就是String類的intern()方法浸踩。

3叔汁、JVM堆?Java?Virtual?Machine?Heap):

存放所有對(duì)象實(shí)例的地方。

新生代检碗,由Eden?Space?和大小相同的兩塊Survivor組成

舊生待据块,存放經(jīng)過(guò)多次垃圾回收仍然存活的對(duì)象

4、直接內(nèi)存Direct Memory):

它并不是虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)的一部分折剃,也不是JAVA虛擬機(jī)規(guī)范中定義的內(nèi)存區(qū)域另假。在JDK1.4中加入了NIO類,引入了一種基于通道(Channel)于緩沖區(qū)(Buffer)的I/O方式怕犁,他可以使用Native函數(shù)庫(kù)直接分配堆外內(nèi)存边篮,然后通過(guò)一個(gè)存儲(chǔ)在JAVA堆里面的DirectByteBuffer對(duì)象作為這塊內(nèi)存的引用進(jìn)行操作己莺。這樣能在一些場(chǎng)景中顯著提高性能,因?yàn)楸苊饬嗽贘AVA堆中和Native堆中來(lái)回復(fù)制數(shù)據(jù)戈轿。




Java內(nèi)存模型

Java內(nèi)存模型即JavaMemory Model凌受,簡(jiǎn)稱JMM。JMM定義了Java 虛擬機(jī)(JVM)在計(jì)算機(jī)內(nèi)存(RAM)中的工作方式凶杖。JVM是整個(gè)計(jì)算機(jī)虛擬模型胁艰,所以JMM是隸屬于JVM的款筑。

Java內(nèi)存模型規(guī)范了Java虛擬機(jī)與計(jì)算機(jī)內(nèi)存是如何協(xié)同工作的智蝠。Java虛擬機(jī)是一個(gè)完整的計(jì)算機(jī)的一個(gè)模型,因此這個(gè)模型自然也包含一個(gè)內(nèi)存模型——又稱為Java內(nèi)存模型奈梳。

Java內(nèi)存模型把Java虛擬機(jī)內(nèi)部劃分為線程棧和堆杈湾。

每一個(gè)運(yùn)行在Java虛擬機(jī)里的線程都擁有自己的線程棧。這個(gè)線程棧包含了這個(gè)線程調(diào)用的方法當(dāng)前執(zhí)行點(diǎn)相關(guān)的信息攘须。一個(gè)線程僅能訪問自己的線程棧漆撞。一個(gè)線程創(chuàng)建的本地變量對(duì)其它線程不可見,僅自己可見于宙。即使兩個(gè)線程執(zhí)行同樣的代碼浮驳,這兩個(gè)線程任然在在自己的線程棧中的代碼來(lái)創(chuàng)建本地變量。因此捞魁,每個(gè)線程擁有每個(gè)本地變量的獨(dú)有版本至会。

所有原始類型的本地變量都存放在線程棧上,因此對(duì)其它線程不可見谱俭。一個(gè)線程可能向另一個(gè)線程傳遞一個(gè)原始類型變量的拷貝奉件,但是它不能共享這個(gè)原始類型變量自身。

堆上包含在Java程序中創(chuàng)建的所有對(duì)象昆著,無(wú)論是哪一個(gè)對(duì)象創(chuàng)建的县貌。這包括原始類型的對(duì)象版本。如果一個(gè)對(duì)象被創(chuàng)建然后賦值給一個(gè)局部變量凑懂,或者用來(lái)作為另一個(gè)對(duì)象的成員變量煤痕,這個(gè)對(duì)象任然是存放在堆上。


一個(gè)本地變量可能是原始類型接谨,在這種情況下摆碉,它總是“呆在”線程棧上。

一個(gè)本地變量也可能是指向一個(gè)對(duì)象的一個(gè)引用疤坝。在這種情況下兆解,引用(這個(gè)本地變量)存放在線程棧上,但是對(duì)象本身存放在堆上跑揉。

一個(gè)對(duì)象可能包含方法锅睛,這些方法可能包含本地變量埠巨。這些本地變量任然存放在線程棧上,即使這些方法所屬的對(duì)象存放在堆上现拒。

一個(gè)對(duì)象的成員變量可能隨著這個(gè)對(duì)象自身存放在堆上辣垒。不管這個(gè)成員變量是原始類型還是引用類型。

靜態(tài)成員變量跟隨著類定義一起也存放在堆上印蔬。

存放在堆上的對(duì)象可以被所有持有對(duì)這個(gè)對(duì)象引用的線程訪問勋桶。當(dāng)一個(gè)線程可以訪問一個(gè)對(duì)象時(shí),它也可以訪問這個(gè)對(duì)象的成員變量侥猬。如果兩個(gè)線程同時(shí)調(diào)用同一個(gè)對(duì)象上的同一個(gè)方法例驹,它們將會(huì)都訪問這個(gè)對(duì)象的成員變量,但是每一個(gè)線程都擁有這個(gè)本地變量的私有拷貝退唠。


Java內(nèi)存模型規(guī)范了Java虛擬機(jī)與計(jì)算機(jī)內(nèi)存是如何協(xié)同工作的鹃锈。Java虛擬機(jī)是一個(gè)完整的計(jì)算機(jī)的一個(gè)模型,因此這個(gè)模型自然也包含一個(gè)內(nèi)存模型——又稱為Java內(nèi)存模型瞧预。

如果你想設(shè)計(jì)表現(xiàn)良好的并發(fā)程序屎债,理解Java內(nèi)存模型是非常重要的。Java內(nèi)存模型規(guī)定了如何和何時(shí)可以看到由其他線程修改過(guò)后的共享變量的值垢油,以及在必須時(shí)如何同步的訪問共享變量盆驹。

原始的Java內(nèi)存模型存在一些不足,因此Java內(nèi)存模型在Java1.5時(shí)被重新修訂滩愁。這個(gè)版本的Java內(nèi)存模型在Java8中人在使用躯喇。

Java內(nèi)存模型內(nèi)部原理

Java內(nèi)存模型把Java虛擬機(jī)內(nèi)部劃分為線程棧和堆。這張圖演示了Java內(nèi)存模型的邏輯視圖惊楼。

每一個(gè)運(yùn)行在Java虛擬機(jī)里的線程都擁有自己的線程棧玖瘸。這個(gè)線程棧包含了這個(gè)線程調(diào)用的方法當(dāng)前執(zhí)行點(diǎn)相關(guān)的信息。一個(gè)線程僅能訪問自己的線程棧檀咙。一個(gè)線程創(chuàng)建的本地變量對(duì)其它線程不可見雅倒,僅自己可見。即使兩個(gè)線程執(zhí)行同樣的代碼弧可,這兩個(gè)線程任然在在自己的線程棧中的代碼來(lái)創(chuàng)建本地變量蔑匣。因此,每個(gè)線程擁有每個(gè)本地變量的獨(dú)有版本棕诵。

所有原始類型的本地變量都存放在線程棧上裁良,因此對(duì)其它線程不可見。一個(gè)線程可能向另一個(gè)線程傳遞一個(gè)原始類型變量的拷貝校套,但是它不能共享這個(gè)原始類型變量自身价脾。

堆上包含在Java程序中創(chuàng)建的所有對(duì)象,無(wú)論是哪一個(gè)對(duì)象創(chuàng)建的笛匙。這包括原始類型的對(duì)象版本侨把。如果一個(gè)對(duì)象被創(chuàng)建然后賦值給一個(gè)局部變量犀变,或者用來(lái)作為另一個(gè)對(duì)象的成員變量,這個(gè)對(duì)象任然是存放在堆上秋柄。

下面這張圖演示了調(diào)用棧和本地變量存放在線程棧上获枝,對(duì)象存放在堆上。

一個(gè)本地變量可能是原始類型骇笔,在這種情況下省店,它總是“呆在”線程棧上。

一個(gè)本地變量也可能是指向一個(gè)對(duì)象的一個(gè)引用笨触。在這種情況下懦傍,引用(這個(gè)本地變量)存放在線程棧上,但是對(duì)象本身存放在堆上旭旭。

一個(gè)對(duì)象可能包含方法谎脯,這些方法可能包含本地變量。這些本地變量任然存放在線程棧上持寄,即使這些方法所屬的對(duì)象存放在堆上。

一個(gè)對(duì)象的成員變量可能隨著這個(gè)對(duì)象自身存放在堆上娱俺。不管這個(gè)成員變量是原始類型還是引用類型稍味。

靜態(tài)成員變量跟隨著類定義一起也存放在堆上。

存放在堆上的對(duì)象可以被所有持有對(duì)這個(gè)對(duì)象引用的線程訪問荠卷。當(dāng)一個(gè)線程可以訪問一個(gè)對(duì)象時(shí)模庐,它也可以訪問這個(gè)對(duì)象的成員變量。如果兩個(gè)線程同時(shí)調(diào)用同一個(gè)對(duì)象上的同一個(gè)方法油宜,它們將會(huì)都訪問這個(gè)對(duì)象的成員變量掂碱,但是每一個(gè)線程都擁有這個(gè)本地變量的私有拷貝。

下圖演示了上面提到的點(diǎn):

兩個(gè)線程擁有一些列的本地變量慎冤。其中一個(gè)本地變量(Local Variable 2)執(zhí)行堆上的一個(gè)共享對(duì)象(Object 3)疼燥。這兩個(gè)線程分別擁有同一個(gè)對(duì)象的不同引用。這些引用都是本地變量蚁堤,因此存放在各自線程的線程棧上醉者。這兩個(gè)不同的引用指向堆上同一個(gè)對(duì)象。

注意披诗,這個(gè)共享對(duì)象(Object 3)持有Object2和Object4一個(gè)引用作為其成員變量(如圖中Object3指向Object2和Object4的箭頭)撬即。通過(guò)在Object3中這些成員變量引用,這兩個(gè)線程就可以訪問Object2和Object4呈队。

這張圖也展示了指向堆上兩個(gè)不同對(duì)象的一個(gè)本地變量剥槐。在這種情況下,指向兩個(gè)不同對(duì)象的引用不是同一個(gè)對(duì)象宪摧。理論上粒竖,兩個(gè)線程都可以訪問Object1和Object5迈喉,如果兩個(gè)線程都擁有兩個(gè)對(duì)象的引用。但是在上圖中温圆,每一個(gè)線程僅有一個(gè)引用指向兩個(gè)對(duì)象其中之一挨摸。


如果兩個(gè)線程同時(shí)執(zhí)行run()方法,就會(huì)出現(xiàn)上圖所示的情景岁歉。run()方法調(diào)用methodOne()方法得运,methodOne()調(diào)用methodTwo()方法。

methodOne()聲明了一個(gè)原始類型的本地變量和一個(gè)引用類型的本地變量锅移。

每個(gè)線程執(zhí)行methodOne()都會(huì)在它們對(duì)應(yīng)的線程棧上創(chuàng)建localVariable1和localVariable2的私有拷貝熔掺。localVariable1變量彼此完全獨(dú)立,僅“生活”在每個(gè)線程的線程棧上非剃。一個(gè)線程看不到另一個(gè)線程對(duì)它的localVariable1私有拷貝做出的修改置逻。

每個(gè)線程執(zhí)行methodOne()時(shí)也將會(huì)創(chuàng)建它們各自的localVariable2拷貝。然而备绽,兩個(gè)localVariable2的不同拷貝都指向堆上的同一個(gè)對(duì)象券坞。代碼中通過(guò)一個(gè)靜態(tài)變量設(shè)置localVariable2指向一個(gè)對(duì)象引用。僅存在一個(gè)靜態(tài)變量的一份拷貝肺素,這份拷貝存放在堆上恨锚。因此,localVariable2的兩份拷貝都指向由MySharedObject指向的靜態(tài)變量的同一個(gè)實(shí)例倍靡。MySharedObject實(shí)例也存放在堆上猴伶。它對(duì)應(yīng)于上圖中的Object3。

注意塌西,MySharedObject類也包含兩個(gè)成員變量他挎。這些成員變量隨著這個(gè)對(duì)象存放在堆上。這兩個(gè)成員變量指向另外兩個(gè)Integer對(duì)象捡需。這些Integer對(duì)象對(duì)應(yīng)于上圖中的Object2和Object4.

注意办桨,methodTwo()創(chuàng)建一個(gè)名為localVariable的本地變量。這個(gè)成員變量是一個(gè)指向一個(gè)Integer對(duì)象的對(duì)象引用栖忠。這個(gè)方法設(shè)置localVariable1引用指向一個(gè)新的Integer實(shí)例崔挖。在執(zhí)行methodTwo方法時(shí),localVariable1引用將會(huì)在每個(gè)線程中存放一份拷貝庵寞。這兩個(gè)Integer對(duì)象實(shí)例化將會(huì)被存儲(chǔ)堆上狸相,但是每次執(zhí)行這個(gè)方法時(shí),這個(gè)方法都會(huì)創(chuàng)建一個(gè)新的Integer對(duì)象捐川,兩個(gè)線程執(zhí)行這個(gè)方法將會(huì)創(chuàng)建兩個(gè)不同的Integer實(shí)例脓鹃。methodTwo方法創(chuàng)建的Integer對(duì)象對(duì)應(yīng)于上圖中的Object1和Object5。

還有一點(diǎn)古沥,MySharedObject類中的兩個(gè)long類型的成員變量是原始類型的瘸右。因?yàn)榻扛@些變量是成員變量,所以它們?nèi)稳浑S著該對(duì)象存放在堆上太颤,僅有本地變量存放在線程棧上苞俘。


并發(fā)編程

在并發(fā)編程領(lǐng)域,有兩個(gè)關(guān)鍵問題:線程之間的通信同步龄章。

線程之間的通信

線程的通信是指線程之間以何種機(jī)制來(lái)交換信息吃谣。在命令式編程中,線程之間的通信機(jī)制有兩種共享內(nèi)存消息傳遞做裙。

1岗憋、共享內(nèi)存的并發(fā)模型里,線程之間共享程序的公共狀態(tài)锚贱,線程之間通過(guò)寫-讀內(nèi)存中的公共狀態(tài)來(lái)隱式進(jìn)行通信仔戈,典型的共享內(nèi)存通信方式就是通過(guò)共享對(duì)象進(jìn)行通信。

2拧廊、消息傳遞的并發(fā)模型里监徘,線程之間沒有公共狀態(tài),線程之間必須通過(guò)明確的發(fā)送消息來(lái)顯式進(jìn)行通信卦绣,在java中典型的消息傳遞方式就是wait()notify()耐量。

線程之間的同步

同步是指程序用于控制不同線程之間操作發(fā)生相對(duì)順序的機(jī)制。

在共享內(nèi)存并發(fā)模型里滤港,同步是顯式進(jìn)行的。程序員必須顯式指定某個(gè)方法或某段代碼需要在線程之間互斥執(zhí)行趴拧。

在消息傳遞的并發(fā)模型里溅漾,由于消息的發(fā)送必須在消息的接收之前,因此同步是隱式進(jìn)行的著榴。



























































































http://www.importnew.com/19612.html

http://ifeve.com/java-memory-model-0/

http://www.cnblogs.com/evan2012/archive/2012/05/09/2489417.html

http://www.cnblogs.com/angeldevil/p/3801189.html

http://www.cnblogs.com/CongLollipop/p/6665606.html

http://ifeve.com/java-memory-model-0/

http://www.importnew.com/19612.html

http://www.cnblogs.com/nexiyi/p/java_memory_model_and_thread.html

http://blog.csdn.net/suifeng3051/article/details/52611310

http://blog.csdn.net/hu1991die/article/details/43052281

http://blog.csdn.net/hu1991die/article/details/43052281


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末添履,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子脑又,更是在濱河造成了極大的恐慌暮胧,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件问麸,死亡現(xiàn)場(chǎng)離奇詭異往衷,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)严卖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門席舍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人哮笆,你說(shuō)我怎么就攤上這事来颤√ぃ” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵福铅,是天一觀的道長(zhǎng)萝毛。 經(jīng)常有香客問我,道長(zhǎng)滑黔,這世上最難降的妖魔是什么笆包? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮拷沸,結(jié)果婚禮上色查,老公的妹妹穿的比我還像新娘。我一直安慰自己撞芍,他們只是感情好秧了,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著序无,像睡著了一般验毡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上帝嗡,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天晶通,我揣著相機(jī)與錄音,去河邊找鬼哟玷。 笑死狮辽,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的巢寡。 我是一名探鬼主播喉脖,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼抑月!你這毒婦竟也來(lái)了树叽?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤谦絮,失蹤者是張志新(化名)和其女友劉穎题诵,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體层皱,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡性锭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了奶甘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片篷店。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出疲陕,到底是詐尸還是另有隱情方淤,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布蹄殃,位于F島的核電站携茂,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏诅岩。R本人自食惡果不足惜讳苦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吩谦。 院中可真熱鬧鸳谜,春花似錦、人聲如沸式廷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)滑废。三九已至蝗肪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蠕趁,已是汗流浹背薛闪。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留俺陋,地道東北人豁延。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像腊状,于是被迫代替她去往敵國(guó)和親术浪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容