線程安全的設(shè)計(jì)技巧

同步工具的使用固然能保障我們代碼線程安全,但是頻繁地使用也會(huì)對(duì)應(yīng)用程序的性能造成負(fù)面影響闯第。因此,在安全與性能之間權(quán)衡是一門(mén)經(jīng)驗(yàn)學(xué)問(wèn)。下面提供了一些應(yīng)用程序使用同步工具時(shí)的技巧零聚。
來(lái)源:Threading Programming Guide__Tips for Thread-Safe Designs

1、最好能避免使用同步工具

同步工具確實(shí)會(huì)影響任何應(yīng)用程序的性能些侍,如果在設(shè)計(jì)上使得某個(gè)資源會(huì)被高度競(jìng)爭(zhēng)隶症,那么線程等待的時(shí)間可能會(huì)更長(zhǎng)。
在實(shí)現(xiàn)并發(fā)時(shí)岗宣,比較優(yōu)雅的使用方式是減少這些并發(fā)任務(wù)之間的交互和依賴(lài)蚂会。如果每個(gè)任務(wù)都在任務(wù)本身的私有數(shù)據(jù)集上運(yùn)行,則不需要鎖等同步工具去保護(hù)這些數(shù)據(jù)耗式。如果必須要多任務(wù)共享單個(gè)數(shù)據(jù)集胁住,可以考慮單獨(dú)為每個(gè)任務(wù)拷貝一份副本,當(dāng)然刊咳,使用時(shí)得權(quán)衡數(shù)據(jù)拷貝成本和同步工具成本的權(quán)衡問(wèn)題彪见。

2、理解同步工具的局限性

同步工具只有應(yīng)用程序中所有線程保持統(tǒng)一使用時(shí)才體現(xiàn)其效果娱挨。舉個(gè)例子余指,如果創(chuàng)建了一個(gè)互斥鎖用于限制對(duì)特定資源的訪問(wèn),那么在操縱資源之前跷坝,所有的線程必須獲得相同的互斥鎖酵镜。如果不這樣做,會(huì)破壞互斥鎖所提供的保護(hù)探孝。

3笋婿、注重代碼的邏輯

使用鎖和內(nèi)存屏障時(shí),應(yīng)該始終考慮它們?cè)诖a中的位置顿颅。
相關(guān)使程序線程安全的示例缸濒,可參考:Thread Safety Summary

4、提防死鎖和活鎖(deadlocks粱腻, livelocks)

當(dāng)線程試圖同時(shí)獲取多個(gè)被鎖的資源時(shí)庇配,就會(huì)可能引發(fā)死鎖。當(dāng)線程A持有加鎖資源a绍些,線程B持有加鎖資源b捞慌,而它們?cè)卺尫沛i之前都企圖獲取對(duì)方線程上的資源,此時(shí)線程A等待線程B釋放資源b柬批,線程B等待線程A釋放資源a啸澡,因此兩者會(huì)一直在等待(阻塞) 袖订。

產(chǎn)生死鎖需要符合的必要條件:
1)互斥條件:指進(jìn)程對(duì)所分配到的資源進(jìn)行排它性使用,即在一段時(shí)間內(nèi)某資源只由一個(gè)進(jìn)程占用嗅虏。如果此時(shí)還有其它進(jìn)程請(qǐng)求資源洛姑,則請(qǐng)求者只能等待,直至占有資源的進(jìn)程用畢釋放皮服。
2)請(qǐng)求和保持條件:指進(jìn)程已經(jīng)保持至少一個(gè)資源楞艾,但又提出了新的資源請(qǐng)求,而該資源已被其它進(jìn)程占有龄广,此時(shí)請(qǐng)求進(jìn)程阻塞硫眯,但又對(duì)自己已獲得的其它資源保持不放。
3)不剝奪條件:指進(jìn)程已獲得的資源择同,在未使用完之前两入,不能被剝奪,只能在使用完時(shí)由自己釋放奠衔。
4)環(huán)路等待條件:指在發(fā)生死鎖時(shí)谆刨,必然存在一個(gè)進(jìn)程——資源的環(huán)形鏈塘娶,即進(jìn)程集合{P0归斤,P1,P2刁岸,···脏里,Pn}中的P0正在等待一個(gè)P1占用的資源;P1正在等待P2占用的資源虹曙,……迫横,Pn正在等待已被P0占用的資源。

活鎖指的是任務(wù)或者執(zhí)行者沒(méi)有被阻塞酝碳,由于某些條件沒(méi)有滿足矾踱,導(dǎo)致一直重復(fù)嘗試,失敗疏哗,嘗試呛讲,失敗。 活鎖和死鎖的區(qū)別在于返奉,處于活鎖的實(shí)體是在不斷的改變狀態(tài)贝搁,所謂的“活”, 而處于死鎖的實(shí)體表現(xiàn)為等待芽偏;活鎖有可能自行解開(kāi)雷逆,死鎖則不能。

百度百科有一段比較粗俗的描述~:
死鎖:迎面開(kāi)來(lái)的汽車(chē)A和汽車(chē)B過(guò)馬路污尉,汽車(chē)A得到了半條路的資源(滿足死鎖發(fā)生條件1:資源訪問(wèn)是排他性的膀哲,我占了路你就不能上來(lái)往产,除非你爬我頭上去),汽車(chē)B占了汽車(chē)A的另外半條路的資源某宪,A想過(guò)去必須請(qǐng)求另一半被B占用的道路(死鎖發(fā)生條件2:必須整條車(chē)身的空間才能開(kāi)過(guò)去捂齐,我已經(jīng)占了一半,尼瑪另一半的路被B占用了)缩抡,B若想過(guò)去也必須等待A讓路奠宜,A是輛蘭博基尼,B是開(kāi)奇瑞QQ的屌絲瞻想,A素質(zhì)比較低開(kāi)窗對(duì)B狂罵:快給老子讓開(kāi)压真,B很生氣,你媽逼的蘑险,老子就不讓?zhuān)ㄋ梨i發(fā)生條件3:在未使用完資源前滴肿,不能被其他線程剝奪),于是兩者相互僵持一個(gè)都走不了(死鎖發(fā)生條件4:環(huán)路等待條件)佃迄,而且導(dǎo)致整條道上的后續(xù)車(chē)輛也走不了泼差。
————————————————————————
活鎖:馬路中間有條小橋,只能容納一輛車(chē)經(jīng)過(guò)呵俏,橋兩頭開(kāi)來(lái)兩輛車(chē)A和B堆缘,A比較禮貌,示意B先過(guò)普碎,B也比較禮貌吼肥,示意A先過(guò),結(jié)果兩人一直謙讓誰(shuí)也過(guò)不去 麻车。

5缀皱、正確地使用Volatile變量

若當(dāng)前已使用互斥鎖保護(hù)代碼,無(wú)須再設(shè)置volatile關(guān)鍵字去保護(hù)需要保護(hù)的變量动猬。因互斥鎖中已經(jīng)包含一個(gè)內(nèi)存屏障啤斗,數(shù)據(jù)的加載和存儲(chǔ)操作的順序得到了保障。如果再使用volatile修飾鎖中變量赁咙,會(huì)強(qiáng)制每次訪問(wèn)都從內(nèi)存中加載 钮莲,帶來(lái)一定的性能損耗,因此可省略volaitle關(guān)鍵字序目。
同時(shí)臂痕,對(duì)比volatile而言,互斥鎖和其他的一些同步機(jī)制是保護(hù)數(shù)據(jù)結(jié)構(gòu)完整性的更好的方法猿涨,因?yàn)関olatil關(guān)鍵字僅保障不從寄存器只從內(nèi)存中加載變量握童,卻不能保障代碼是否能正確地訪問(wèn)變量。

參考資料:
1叛赚、stackoverflow
2澡绩、死鎖
3稽揭、活鎖
4、ios多線程死鎖解析
5肥卡、維基百科

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末溪掀,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子步鉴,更是在濱河造成了極大的恐慌揪胃,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件氛琢,死亡現(xiàn)場(chǎng)離奇詭異喊递,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)阳似,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)骚勘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人撮奏,你說(shuō)我怎么就攤上這事俏讹。” “怎么了畜吊?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵泽疆,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我定拟,道長(zhǎng)于微,這世上最難降的妖魔是什么逗嫡? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任青自,我火速辦了婚禮,結(jié)果婚禮上驱证,老公的妹妹穿的比我還像新娘延窜。我一直安慰自己,他們只是感情好抹锄,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布逆瑞。 她就那樣靜靜地躺著,像睡著了一般伙单。 火紅的嫁衣襯著肌膚如雪获高。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,821評(píng)論 1 290
  • 那天吻育,我揣著相機(jī)與錄音念秧,去河邊找鬼。 笑死布疼,一個(gè)胖子當(dāng)著我的面吹牛摊趾,可吹牛的內(nèi)容都是我干的币狠。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼砾层,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼漩绵!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起肛炮,我...
    開(kāi)封第一講書(shū)人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤止吐,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后侨糟,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體祟印,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年粟害,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蕴忆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡悲幅,死狀恐怖套鹅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情汰具,我是刑警寧澤卓鹿,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站留荔,受9級(jí)特大地震影響吟孙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜聚蝶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一杰妓、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧碘勉,春花似錦巷挥、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至胜嗓,卻和暖如春高职,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背辞州。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工怔锌, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓产禾,卻偏偏與公主長(zhǎng)得像排作,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子亚情,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349