并發(fā)Bug的源頭

講實(shí)話聽到這個(gè)問題骏啰,不太熟悉并發(fā)編程的同學(xué)有點(diǎn)暈节吮,你可能只能答個(gè)因?yàn)槎嗑€程之間的競爭共享資源啊。對說的沒錯(cuò)判耕。

但是呢感覺不夠亮眼透绩!我們的目的就是讓面試官眼前一亮,讓他顫抖壁熄!心里鼓掌:"牛批牛批!"


萬劍歸宗

多線程帚豪,給我們的感覺像啥?就像《風(fēng)云》里面的無名的"萬劍歸宗"草丧!《雪中悍刀行》里面老劍神李淳罡一聲“劍來狸臣!”。嘩嘩嘩的好多劍同時(shí)操作著一起飛昌执!多帥哦烛亦!

但實(shí)際上CPU的執(zhí)行是有時(shí)間片的诈泼,也就是其實(shí)我們多線程不是同一時(shí)間一起執(zhí)行的,是每個(gè)線程執(zhí)行一會兒就換一個(gè)上煤禽,但是時(shí)間片很短铐达,所以我們感覺上是一起執(zhí)行的。當(dāng)然多核CPU的話檬果,每個(gè)CPU是并行的瓮孙,但是我們CPU顆數(shù)哪有我們的線程多!

大家都知道我們電腦有CPU选脊,內(nèi)存杭抠,IO設(shè)備。IO讀取時(shí)最慢的知牌,然后是內(nèi)存讀取祈争,最快的是CPU的執(zhí)行。那因?yàn)閮?nèi)存太慢了角寸,跟不上CPU菩混,所以CPU搞了個(gè)緩存。就是因?yàn)檫@個(gè)緩存再加上多顆CPU并發(fā)就出問題了扁藕。

舉個(gè)例子


上面這個(gè)程序很簡單沮峡,但是如果有兩個(gè)線程A和B,分別CPU-A和CPU-B中同時(shí)addOne()可能會出現(xiàn)什么問題呢亿柑?

同時(shí)的線程A把a(bǔ)從內(nèi)存中取到CPU-A緩存中邢疙,緩存中a的值是0,線程B把a(bǔ)從內(nèi)存中取到CPU-B緩存中緩存中a的值是0望薄。然后它們各自+了個(gè)1疟游。這時(shí)候在它們的各自的緩存中a的值都是1。那之后寫入內(nèi)存中痕支,是不是a就變成1了颁虐?

那我們加了兩次是不是少了一次了!這是問題就是可見性問題了卧须!CPU-A的緩存的值CPU-B不可見另绩!這就是可見性的根本原因。

我們再來說一下原子性花嘶,首先原子性指的就是一個(gè)或多個(gè)操作在CPU中執(zhí)行不會被中斷的特性稱為原子性笋籽。

我們的JAVA語言是高級語言。高級語言是怎么個(gè)情況椭员。就是我們一條java代碼涵蓋了好幾條底層指令车海。比如我們上面的a=a+1;把它轉(zhuǎn)換成CPU指令至少有三條。

第一條:把a(bǔ)從內(nèi)存拿到寄存器中隘击;

第二條:寄存器中+1侍芝;

第三條:結(jié)果寫入緩存或內(nèi)存中喘沿;

那按照CPU的原子性,它是指令級別的竭贩!一條指令是不會被中斷的,所以說在我們以為a=a+1;是原子級別的莺禁,實(shí)際上在CPU看來不是留量。

所以呢如果此時(shí)有兩個(gè)線程同時(shí)執(zhí)行,那可能線程A執(zhí)行到第二條的時(shí)候哟冬,時(shí)間片到了÷ハǎ現(xiàn)在換線程B上了,然后線程B又把a(bǔ)從內(nèi)存中拿到浩峡,然后+1返回結(jié)果可岂,此時(shí)換到了線程A,線程A繼續(xù)執(zhí)行第三條翰灾。那情況就是又錯(cuò)了缕粹。

還沒完呢!我們編譯器或解釋器的優(yōu)化可能帶來意料不到的問題纸淮!為了優(yōu)化性能平斩,它可能會改變語句執(zhí)行的順序,也就是指令重排咽块!

最經(jīng)典的就是單例的雙重檢查了绘面!


看起來都加鎖了好像沒問題了,而問題就出在 instance = new Singleton(); 上

我們認(rèn)為的new操作就是:

1.分配一塊內(nèi)存

2.在內(nèi)存上初始化Singleton

3.將內(nèi)存地址賦值給instance

而指令重排之后:

1.分配一塊內(nèi)存

2.將內(nèi)存地址分配給instance

3.初始化Singleton

這會導(dǎo)致什么問題呢侈沪?假設(shè)線程A已經(jīng)執(zhí)行到new Singleton()的指令2了揭璃,然后時(shí)間片到了,這時(shí)候線程B也調(diào)用getInstance();到第一個(gè)instance==null時(shí)候亭罪,直接返回了瘦馍。很開心拿到了對象了!而實(shí)際上對象還沒初始化呢皆撩!所以用了的話就是空指針了扣墩!

這就是有序性問題了!

所以一共有三大特性:可見性扛吞、原子性呻惕、有序性。并發(fā)的問題都逃不過這三大特性滥比!JAVA的內(nèi)存模型其實(shí)有很多都是解決這幾種問題的亚脆,比如上面單例的例子instance由 volatile來聲明一下,這樣就禁止指令重排了盲泛!

希望通過今天的分析大家能深入理解這三大特性濒持!寫出健壯的并發(fā)代碼键耕!



最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市柑营,隨后出現(xiàn)的幾起案子屈雄,更是在濱河造成了極大的恐慌,老刑警劉巖官套,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件酒奶,死亡現(xiàn)場離奇詭異,居然都是意外死亡奶赔,警方通過查閱死者的電腦和手機(jī)惋嚎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來站刑,“玉大人另伍,你說我怎么就攤上這事〗事茫” “怎么了摆尝?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長玻靡。 經(jīng)常有香客問我结榄,道長,這世上最難降的妖魔是什么囤捻? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任臼朗,我火速辦了婚禮,結(jié)果婚禮上蝎土,老公的妹妹穿的比我還像新娘视哑。我一直安慰自己,他們只是感情好誊涯,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布挡毅。 她就那樣靜靜地躺著,像睡著了一般暴构。 火紅的嫁衣襯著肌膚如雪跪呈。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天取逾,我揣著相機(jī)與錄音耗绿,去河邊找鬼。 笑死砾隅,一個(gè)胖子當(dāng)著我的面吹牛误阻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼究反,長吁一口氣:“原來是場噩夢啊……” “哼寻定!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起精耐,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤狼速,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后卦停,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體唐含,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年沫浆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片滚秩。...
    茶點(diǎn)故事閱讀 40,865評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡专执,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出郁油,到底是詐尸還是另有隱情本股,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布桐腌,位于F島的核電站拄显,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏案站。R本人自食惡果不足惜躬审,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蟆盐。 院中可真熱鬧承边,春花似錦、人聲如沸石挂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽痹愚。三九已至富岳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間拯腮,已是汗流浹背窖式。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留疾瓮,地道東北人脖镀。 一個(gè)月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蜒灰。 傳聞我的和親對象是個(gè)殘疾皇子弦蹂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評論 2 361

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