欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

Java內(nèi)存模型詳解[轉(zhuǎn)]

系統(tǒng) 1828 0

內(nèi)存模型 (memory model)
內(nèi)存模型描述的是程序中各變量(實例域、靜態(tài)域和數(shù)組元素)之間的關(guān)系,以及在實際計算機(jī)系統(tǒng)中將變量存儲到內(nèi)存和從內(nèi)存取出變量這樣的低層細(xì)節(jié).

不同平臺間的處理器架構(gòu)將直接影響內(nèi)存模型的結(jié)構(gòu).

在C或C++中, 可以利用不同操作平臺下的內(nèi)存模型來編寫并發(fā)程序. 但是, 這帶給開發(fā)人員的是, 更高的學(xué)習(xí)成本.
相比之下, java利用了自身虛擬機(jī)的優(yōu)勢, 使內(nèi)存模型不束縛于具體的處理器架構(gòu), 真正實現(xiàn)了跨平臺.
(針對hotspot jvm, jrockit等不同的jvm, 內(nèi)存模型也會不相同)

內(nèi)存模型的特征:
a, Visibility 可視性 (多核,多線程間數(shù)據(jù)的共享)
b, Ordering 有序性 (對內(nèi)存進(jìn)行的操作應(yīng)該是有序的)


--------------------------------------------------------------------------------


java 內(nèi)存模型 ( java memory model )
根據(jù)Java Language Specification中的說明, jvm系統(tǒng)中存在一個主內(nèi)存(Main Memory或Java Heap Memory),Java中所有變量都儲存在主存中,對于所有線程都是共享的。

每條線程都有自己的工作內(nèi)存(Working Memory),工作內(nèi)存中保存的是主存中某些變量的拷貝,線程對所有變量的操作都是在工作內(nèi)存中進(jìn)行,線程之間無法相互直接訪問,變量傳遞均需要通過主存完成。

?

?

其中, 工作內(nèi)存里的變量, 在多核處理器下, 將大部分儲存于處理器高速緩存中, 高速緩存在不經(jīng)過內(nèi)存時, 也是不可見的.

jmm怎么體現(xiàn) 可視性(Visibility) ?
在jmm中, 通過并發(fā)線程修改變量值, 必須將線程變量同步回主存后, 其他線程才能訪問到.

jmm怎么體現(xiàn) 有序性(Ordering) ?
通過java提供的同步機(jī)制或volatile關(guān)鍵字, 來保證內(nèi)存的訪問順序.

?

--------------------------------------------------------------------------------


緩存一致性(cache coherency)

什么是緩存一致性?
它是一種管理多處理器系統(tǒng)的高速緩存區(qū)結(jié)構(gòu),其可以保證數(shù)據(jù)在高速緩存區(qū)到內(nèi)存的傳輸中不會丟失或重復(fù)。(來自wikipedia)

舉例理解:
假如有一個處理器有一個更新了的變量值位于其緩存中,但還沒有被寫入主內(nèi)存,這樣別的處理器就可能會看不到這個更新的值.

解決緩存一致性的方法?
a, 順序一致性模型:
要求某處理器對所改變的變量值立即進(jìn)行傳播, 并確保該值被所有處理器接受后, 才能繼續(xù)執(zhí)行其他指令.

b, 釋放一致性模型: (類似jmm cache coherency)
允許處理器將改變的變量值延遲到釋放鎖時才進(jìn)行傳播.


--------------------------------------------------------------------------------


jmm緩存一致性模型 - "happens-before ordering(先行發(fā)生排序)"

一般情況下的示例程序:

x = 0;
y = 0;
i = 0;
j = 0;

// thread A
y = 1;
x = 1;

// thread B
i = x;
j = y;

在如上程序中, 如果線程A,B在無保障情況下運行, 那么i,j各會是什么值呢?

答案是, 不確定. (00,01,10,11都有可能出現(xiàn))
這里沒有使用java同步機(jī)制, 所以 jmm 有序性和可視性 都無法得到保障.

happens-before ordering( 先行發(fā)生排序) 如何避免這種情況?
排序原則已經(jīng)做到:
a, 在程序順序中, 線程中的每一個操作, 發(fā)生在當(dāng)前操作后面將要出現(xiàn)的每一個操作之前.
b, 對象監(jiān)視器的解鎖發(fā)生在等待獲取對象鎖的線程之前.
c, 對volitile關(guān)鍵字修飾的變量寫入操作, 發(fā)生在對該變量的讀取之前.
d, 對一個線程的 Thread.start() 調(diào)用 發(fā)生在啟動的線程中的所有操作之前.
e, 線程中的所有操作 發(fā)生在從這個線程的 Thread.join()成功返回的所有其他線程之前.

為了實現(xiàn) happends-before ordering原則, java及jdk提供的工具:
a, synchronized關(guān)鍵字
b, volatile關(guān)鍵字
c, final變量
d, java.util.concurrent.locks包(since jdk 1.5)
e, java.util.concurrent.atmoic包(since jdk 1.5)
...

使用了happens-before ordering的例子:

Java內(nèi)存模型詳解[轉(zhuǎn)] ??
?

(1) 獲取對象監(jiān)視器的鎖(lock)

(2) 清空工作內(nèi)存數(shù)據(jù), 從主存復(fù)制變量到當(dāng)前工作內(nèi)存, 即同步數(shù)據(jù) (read and load)

(3) 執(zhí)行代碼,改變共享變量值 (use and assign)

(4) 將工作內(nèi)存數(shù)據(jù)刷回主存 (store and write)

(5) 釋放對象監(jiān)視器的鎖 (unlock)

注意: 其中4,5兩步是同時進(jìn)行的.

這邊最核心的就是第二步, 他同步了主內(nèi)存,即前一個線程對變量改動的結(jié)果,可以被當(dāng)前線程獲知!(利用了happens-before ordering原則)

對比之前的例子
如果多個線程同時執(zhí)行一段未經(jīng)鎖保護(hù)的代碼段,很有可能某條線程已經(jīng)改動了變量的值,但是其他線程卻無法看到這個改動,依然在舊的變量值上進(jìn)行運算,最終導(dǎo)致不可預(yù)料的運算結(jié)果。


--------------------------------------------------------------------------------


經(jīng)典j2ee設(shè)計模式Double-Checked Locking失效問題
雙重檢查鎖定失效問題,一直是JMM無法避免的缺陷之一.了解DCL失效問題, 可以幫助我們深入JMM運行原理.

要展示DCL失效問題, 首先要理解一個重要概念- 延遲加載(lazy loading).

非單例的單線程延遲加載示例:

    class Foo
{
?private Resource res = null;
?public Resource getResource()
?{
??// 普通的延遲加載
??if (res == null)
??res = new Resource();
??return res;
?}
}
  
    非單例的 多線程延遲加載示例:
Class Foo
{
?Private Resource res = null;
?Public synchronized Resource getResource()
?{
??// 獲取實例操作使用同步方式, 性能不高
??If (res == null) res = new Resource();
??return res;
?}
}
  
    非單例的 DCL多線程延遲加載示例:
Class Foo
{
?Private Resource res = null;
?Public Resource getResource()
?{
??If (res == null)
??{
???//只有在第一次初始化時,才使用同步方式.
???synchronized(this)
???{
????if(res == null)
????{
?????res = new Resource();
????}
???}
??}
??return res;
?}
}

  

?

Double-Checked Locking看起來是非常完美的。但是很遺憾,根據(jù)Java的語言規(guī)范,上面的代碼是不可靠的。

出現(xiàn)上述問題, 最重要的2個原因如下:
1, 編譯器優(yōu)化了程序指令, 以加快cpu處理速度.
2, 多核cpu動態(tài)調(diào)整指令順序, 以加快并行運算能力.

問題出現(xiàn)的順序:
1, 線程A, 發(fā)現(xiàn)對象未實例化, 準(zhǔn)備開始實例化
2, 由于編譯器優(yōu)化了程序指令, 允許對象在構(gòu)造函數(shù)未調(diào)用完前, 將 共享變量的引用指向 部分構(gòu)造的對象, 雖然對象未完全實例化, 但已經(jīng)不為null了.
3, 線程B, 發(fā)現(xiàn)部分構(gòu)造的對象已不是null, 則直接返回了該對象.

不過, 一些著名的開源框架, 包括jive,lenya等也都在使用DCL模式, 且未見一些極端異常.
說明, DCL失效問題的出現(xiàn)率還是比較低的.
接下來就是性能與穩(wěn)定之間的選擇了?

DCL的替代 Initialize-On-Demand :

    public class Foo {
    // 似有靜態(tài)內(nèi)部類, 只有當(dāng)有引用時, 該類才會被裝載
    private static class LazyFoo {
       public static Foo foo = new Foo();
    }

    public static Foo getInstance() {
       return LazyFoo.foo;
    }
} 
  

?維基百科的DCL解釋:
http://en.wikipedia.org/wiki/Double-checked_locking

DCL的完美解決方案:
http://www.theserverside.com/patterns/thread.tss?thread_id=39606

?

總結(jié):
多線程編程, 針對有寫操作的變量, 必須 保證其所有引用點與主存中數(shù)據(jù)一致(考慮采用同步或volatile) .

?

本文來自CSDN博客,轉(zhuǎn)載請標(biāo)明出處: http://blog.csdn.net/leeshaoqun/archive/2009/02/19/3910022.aspx

Java內(nèi)存模型詳解[轉(zhuǎn)]


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 热99在线| 三级在线观看 | 欧美淫 | 在线视频观看国产 | 亚洲 欧美 日韩中文字幕一区二区 | 国产三级做爰在线观看视频 | a在线观看欧美在线观看 | 亚洲 中文 欧美 日韩 在线观看 | 看一级毛片国产一级毛片 | 欧美综合自拍亚洲综合网 | 亚洲天堂免费看 | 亚洲视频三区 | av色站| 亚洲第一页在线观看 | 国产三级在线观看a | 综合第一页| 搞黄网站免费观看 | 日本中文字幕视频 | 天天操人人爱 | 色www精品视频在线观看 | 2022国产91精品久久久久久 | 欧美视频在线第一页 | 久久中文字幕网 | 99热久久精品免费精品 | 狠狠色噜噜综合社区 | 日本美女久久 | 亚洲av毛片一区二区久久 | 国产一区在线免费观看 | 亚洲一区二区在线视频 | 亚洲一区二区三区在线免费观看 | 亚洲成人精品 | 911福利视频 | 日本精品视频 | 东京不太热在线新视频 | 狠狠色噜噜狠狠狠狠97影音先锋 | 欧美黄色片在线观看 | 污网站免费 | 欧洲色吧| 国产亚洲精品久久久极品美女 | 美女午夜影院 | 91精品午夜|