JMM內(nèi)存模型,JVM分配策略,Volatile+AtomicXXX實(shí)現(xiàn)同步

為了深入理解CAS的,我們從以下幾個維度去探究CAS义起,然后再去考慮為什么出現(xiàn)ABA問題。

1默终、CAS是什么?
2犁罩、為什么需要CAS算法齐蔽?
3、CAS解決的是什么問題床估?
4含滴、在jdk中有哪些是基于CAS實(shí)現(xiàn)的?
5丐巫、CAS底層實(shí)現(xiàn)原理是什么谈况?
6源哩、如何自己編寫一個類似CAS算法的實(shí)現(xiàn)【簡單版本】
7、CAS有哪些問題鸦做?
8励烦、CAS的ABA問題到底是什么意思?如何解決ABA問題泼诱?

CAS是什么坛掠?

CAS:一個算法,全稱為Compare And Swap治筒,比較且交換屉栓。在CAS中存在三個值,
V:內(nèi)存值
A:舊值或者叫預(yù)期值
B:更新值
當(dāng)且僅當(dāng)A==V (預(yù)期值==內(nèi)存值)耸袜,才會出現(xiàn)V=B友多,將更新值賦給內(nèi)存值,否則什么都不做堤框。
問題:為什么需要CAS算法域滥,到底CAS在做什么?三個值分別是什么意思蜈抓?
接下來我們通過一個個的測試用例去探究CAS:

測試用例1

在多線程情景下:

多線程情景下修改值

結(jié)果:

多線程情景下修改值

結(jié)論:在多線程下启绰,無法通過主線程改變其他線程中的內(nèi)容。

探究原因:

  • java內(nèi)存模型(JMM:java memory mode)
  • 多線程下如何處理共享數(shù)據(jù)沟使?


    Java內(nèi)存模型

Java內(nèi)存模型的主要目標(biāo)是定義程序中各個變量的訪問規(guī)則委可,即在虛擬機(jī)中將變量存儲到內(nèi)存和從內(nèi)存中取出變量這樣底層細(xì)節(jié)。此處的變量與Java編程時所說的變量不一樣腊嗡,指包括了實(shí)例字段着倾、靜態(tài)字段和構(gòu)成數(shù)組對象的元素,但是不包括局部變量與方法參數(shù)燕少,后者是線程私有的卡者,不會被共享棺亭。
Java內(nèi)存模型中規(guī)定了所有的變量都存儲在主內(nèi)存中,每條線程還有自己的工作內(nèi)存嗽桩,線程的工作內(nèi)存中保存了該線程使用到的變量到主內(nèi)存副本拷貝凄敢,線程對變量的所有操作(讀取、賦值)都必須在工作內(nèi)存中進(jìn)行涝缝,而不能直接讀寫主內(nèi)存中的變量。不同線程之間無法直接訪問對方工作內(nèi)存中的變量罐氨,線程間變量值的傳遞均需要在主內(nèi)存來完成栅隐。

注意:這里的主內(nèi)存、工作內(nèi)存與Java內(nèi)存區(qū)域的Java堆谨究、棧胶哲、方法區(qū)不是同一層次內(nèi)存劃分潭辈,這兩者基本上沒有關(guān)系

測試用例2:解決可見性問題

解決方案:通過在共享變量上加入volatile關(guān)鍵詞萎胰。volatile關(guān)鍵詞只能保證內(nèi)存可見性,而不能保證原子性。 【ps榔组,關(guān)于volatile我們這次不做探究联逻,當(dāng)然這里除了這種方式之外還有其他解決辦法包归,我們也暫且先不做深入】

加入volatile測試代碼:

volatile測試代碼

結(jié)果:

測試結(jié)果

測試用例3:測試原子性問題

測試用例3:測試原子性問題

結(jié)果:

測試結(jié)果

問題: 通過volatile不能保證我們原來數(shù)據(jù)的原子性問題换可,繼續(xù)往下深入

測試用例4:解決原子性問題

測試用例4:解決原子性問題

注意這里的標(biāo)注區(qū)域,通過AtomicInteger保證原子性

結(jié)果:

測試結(jié)果

解決方案:通過使用java.util.concurrent.atomic.AtomicInteger幫助我們解決原子性問題译荞,而截至到這里我們才真正意義上準(zhǔn)備接觸CAS算法吞歼。這里對于AtomicXXX 不多做擴(kuò)展,我們回來繼續(xù)了解CAS本辐。

CAS解決了什么問題慎皱?

CAS幫助我們解決了數(shù)據(jù)一致性問題叶骨,或者是在上述的例子中忽刽,我們通過AtomicXXX類確保數(shù)據(jù)的原
子性。這里的數(shù)據(jù)一致性我們已經(jīng)在多線程情景下去模擬過了今膊。
并且在高并發(fā)CAS算法也能幫助我們很好的處理數(shù)據(jù)一致性問題斑唬,且它的實(shí)現(xiàn)是一種基于樂觀鎖的
策略實(shí)現(xiàn)黎泣。這樣要比直接使用Synchronized要來的更加高效抒倚,但是這里注意CAS本身的算法
實(shí)現(xiàn)我們說是不穩(wěn)定的由于這個問題也出現(xiàn)了我們說的ABA問題。

在jdk中有哪些是基于CAS實(shí)現(xiàn)的含蓉?

java.utit.concurrent.*;就是基于CAS算法實(shí)現(xiàn)的馅扣。沒有CAS就沒有這個包呆抑;
PS:深入擴(kuò)展一下,比如jvm對于對象分配時也會使用CAS算法厌殉。

java堆中的內(nèi)存分配【這里簡單擴(kuò)展】

我們都知道當(dāng)執(zhí)行new操作的時候,此時其實(shí)對象在堆中分配大小的空間是已經(jīng)確定了的器紧,因?yàn)槲覀?知道java是強(qiáng)類型語言铲汪。不同數(shù)據(jù)類型在堆中所占空間時確定的罐柳。
那么當(dāng)空間確定之后jvm到底是如何分配的呢?

內(nèi)存分配策略:

單線程分配策略

指針碰撞

一般適用于內(nèi)存絕對規(guī)整的[內(nèi)存是否規(guī)整取決于回收策略]齿梁,分配空間時只是通過指針向空閑內(nèi)存中移動創(chuàng)建對象大小的位置即可勺择。

空閑列表

一般適用于內(nèi)存非規(guī)整的省核,此時jvm內(nèi)部維護(hù)了一個列表[內(nèi)存列表]昆码。這個列表中記錄哪些空間時空閑的。分配空間時會在這個列表中查看笔刹,找尋合適的區(qū)域,然后進(jìn)行使用萌壳。

多線程分配策略

ps:給一個對象分配空間時袱瓮,其實(shí)不是原子操作的,需要一下幾步:

  • 查找空閑列表(這里我們假設(shè)大多數(shù)情況下內(nèi)存都是非規(guī)整的以示一般性)
  • 分配內(nèi)存
  • 修改內(nèi)存列表 等操作

第一種多線程分配策略:CAS

jvm通過cas和失敗重試機(jī)制保證分配內(nèi)存之后的更新等操作的原子性绊起。

第二種多線程分配策略:TLAB

每個線程會在java堆中分配一個內(nèi)存[這個內(nèi)存比較小]虱歪,這個內(nèi)存稱之為本地線程分配緩沖區(qū)[TLAB],線程內(nèi)部如果需要分配內(nèi)存會首先在這個TALB上分配,避免線程沖突师枣,只有緩沖區(qū)用完之后才會在分配內(nèi)存時通過CAS操作分配更大的內(nèi)存空間萧落。jdk1.5之后默認(rèn)開啟TLAB,當(dāng)然可以手動關(guān)閉:-xx:+/-UseTLAB進(jìn)行配置陨倡。

我們正在這里先討論到這里兴革,下次繼續(xù)補(bǔ)齊剩余內(nèi)容爹脾,當(dāng)然在以上內(nèi)容中我們有拋出了一些新的問題:

  • volatile關(guān)鍵詞的同步機(jī)制 有哪些優(yōu)缺點(diǎn)呢灵妨?
  • java中的悲觀鎖除了Synchronized之外還有哪些?
  • 樂觀鎖的實(shí)現(xiàn)機(jī)制是什么?
  • 線程同步策略有哪些货抄?

以上內(nèi)容我們后續(xù)在繼續(xù)攻破V熳L傥!嘿嘿分别,奸計(jì)得逞耘斩,你以為你學(xué)會了一個東西桅咆,其實(shí)你是踩到坑里了,哈哈荚虚。請叫我坑王。最后以上內(nèi)容中可能有不詳之處却邓,大家觀看時一定要存疑腊徙。

書上檬某、別人的不一定是對的恢恼,自己測試才能測出真理。

實(shí)踐是檢驗(yàn)真理的的唯一途徑

下篇內(nèi)容地址:http://www.reibang.com/p/fbab74f4fa74

版權(quán)聲明:本文為原創(chuàng)文章漓踢,未經(jīng)博主允許不責(zé)轉(zhuǎn)載喧半。
原文地址:http://www.reibang.com/p/15f17da87ba6

參考文檔:

https://blog.csdn.net/u010425776/article/details/51192448

http://ifeve.com/atomic-operation/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末挺据,一起剝皮案震驚了整個濱河市扁耐,隨后出現(xiàn)的幾起案子产阱,更是在濱河造成了極大的恐慌,老刑警劉巖酿矢,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蜜暑,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)之众,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門依许,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人膘婶,你說我怎么就攤上這事蛀醉。” “怎么了脊岳?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵割捅,是天一觀的道長亿驾。 經(jīng)常有香客問我,道長颊乘,這世上最難降的妖魔是什么乏悄? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任檩小,我火速辦了婚禮,結(jié)果婚禮上规求,老公的妹妹穿的比我還像新娘阻肿。我一直安慰自己沮尿,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布赴邻。 她就那樣靜靜地躺著,像睡著了一般奸焙。 火紅的嫁衣襯著肌膚如雪与帆。 梳的紋絲不亂的頭發(fā)上臊泌,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機(jī)與錄音茶凳,去河邊找鬼贮喧。 笑死猪狈,一個胖子當(dāng)著我的面吹牛雇庙,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播疆前,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼童太,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了书释?” 一聲冷哼從身側(cè)響起爆惧,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤锨能,失蹤者是張志新(化名)和其女友劉穎肴捉,沒想到半個月后叔收,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體饺律,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡复濒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年巧颈,在試婚紗的時候發(fā)現(xiàn)自己被綠了袖扛。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蛆封。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡惨篱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出琢融,到底是詐尸還是另有隱情簿寂,我是刑警寧澤陶耍,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站泊碑,受9級特大地震影響馒过,放射性物質(zhì)發(fā)生泄漏酗钞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一嘹锁、第九天 我趴在偏房一處隱蔽的房頂上張望着裹。 院中可真熱鬧,春花似錦摔竿、人聲如沸继低。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽梦裂。三九已至年柠,卻和暖如春褪迟,著一層夾襖步出監(jiān)牢的瞬間味赃,已是汗流浹背掀抹。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留城榛,地道東北人狠持。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像甜刻,于是被迫代替她去往敵國和親得院。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

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