Java并發(fā)編程實(shí)戰(zhàn) Chapt4 對象的組合

4.1 設(shè)計(jì)線程安全的類

  • 找出構(gòu)成對象狀態(tài)的所有變量
  • 找出約束狀態(tài)變量的不變性條件
  • 建立對象狀態(tài)的并發(fā)訪問管理策略

如果對象中的所有的域都是基本類型的變量,那么這些域?qū)?gòu)成對象的全部狀態(tài)

  • 對于含有n個(gè)基本類型的對象,其狀態(tài)就是這些域構(gòu)成的n元組。

如果在對象的域中引用了其他對象征绎,那么該對象的狀態(tài)將包含被引用對象的域。

4.1.1 收集同步需求

對象與變量都有一個(gè)狀態(tài)空間,即所有可能的取值擒滑。狀態(tài)空間越小,就越容易判斷線程的狀態(tài)叉弦。final類型的域使用得越多丐一,就越能簡化對象可能狀態(tài)的分析過程。
不變性條件:用于判斷狀態(tài)是否有效
后驗(yàn)條件:用于判斷狀態(tài)遷移是否有效
如果某些狀態(tài)是無效的淹冰,那么必須對底層的變量進(jìn)行封裝库车,否則客戶代碼可能會(huì)使對象處于無效狀態(tài)。如果在某個(gè)操作中存在無效的狀態(tài)轉(zhuǎn)換樱拴,那么該操作必須是原子的柠衍。如果在一個(gè)不變性條件中包含多個(gè)變量,那么在執(zhí)行任何訪問相關(guān)變量的操作時(shí)晶乔,都必須持有保護(hù)這些變量的鎖珍坊。**

4.1.2 依賴狀態(tài)的操作

先驗(yàn)條件:在調(diào)用方法之前必須為真的條件
后驗(yàn)條件:方法順利執(zhí)行完畢之后必須為真的條件
依賴狀態(tài)的操作:操作中包含有基于狀態(tài)的先驗(yàn)條件

  • eg. 不能從空隊(duì)列中移除一個(gè)元素

在單線程程序中,如果某個(gè)操作無法滿足先驗(yàn)條件正罢,那么就只能失敗阵漏。但在并發(fā)程序中,先驗(yàn)條件可能會(huì)由于其他線程執(zhí)行的操作而變成真腺怯。在并發(fā)程序中要一直等到先驗(yàn)條件為真袱饭,然后再執(zhí)行該操作。**
實(shí)現(xiàn):

  • 阻塞隊(duì)列(BlockingQueue…)
  • 信號量(Semaphore)

4.1.3 狀態(tài)的所有權(quán)

4.2 實(shí)例封閉

當(dāng)一個(gè)對象被封裝到另一個(gè)對象中時(shí)呛占,能夠訪問被封裝對象的所有代碼路徑都是已知的虑乖。與對象可以由整個(gè)程序訪問的情況相比,更易于對代碼進(jìn)行分析晾虑。通過將封閉機(jī)制與合適的加鎖策略結(jié)合起來疹味,可以確保以線程安全的方式來使用非線程安全的對象。
將數(shù)據(jù)封裝在對象內(nèi)部帜篇,可以將數(shù)據(jù)的訪問限制在對象的方法上糙捺,從而更容易確保線程在訪問數(shù)據(jù)時(shí)總能持有正確的鎖。**


實(shí)例封閉是構(gòu)建線程安全類的一個(gè)最簡單方式笙隙。
實(shí)例封閉還使得不同的狀態(tài)變量可以由不同的鎖來保護(hù)洪灯。
Java的包裝器工廠(eg. Collections.synchronizedList),只要包裝器對象擁有對底層容器對象的唯一引用(即把底層容器對象封閉在包裝器中)竟痰,那么它就是線程安全的签钩。對底層容器對象的所有訪問必須通過包裝器來進(jìn)行掏呼。
當(dāng)發(fā)布其他對象時(shí),例如迭代器或內(nèi)部的類實(shí)例铅檩,可能會(huì)間接地發(fā)布被封閉對象憎夷,同樣會(huì)使被封閉對象逸出。
封閉機(jī)制更易于構(gòu)造線程安全的類昧旨,因?yàn)楫?dāng)封閉類的狀態(tài)時(shí)拾给,在分析類的線程安全性時(shí)就無須檢查整個(gè)程序。

4.2.1 Java監(jiān)視器模式

遵循Java監(jiān)視器模式的對象會(huì)把對象的所有可變狀態(tài)都封裝起來兔沃,并由對象自己的內(nèi)置鎖來保護(hù)蒋得。
Java監(jiān)視器模式的主要優(yōu)勢在于它的簡單性。細(xì)粒度的加鎖策略則可以提高伸縮性粘拾。
私有鎖

4.2.2 示例:車輛追蹤



4.3 線程安全性的委托

4.3.1 示例:基于委托的車輛追蹤器


4.3.2 獨(dú)立的狀態(tài)變量

多個(gè)變量之間是彼此獨(dú)立的窄锅,則可以將線程安全性委托給多個(gè)狀態(tài)變量。
組合而成的類不會(huì)在其包含的多個(gè)狀態(tài)變量上增加任何不變性條件缰雇。

4.3.3 當(dāng)委托失效時(shí)

如果某個(gè)類含有復(fù)合操作,那么僅靠委托不足以實(shí)現(xiàn)線程安全性追驴。在這種情況下械哟,這個(gè)類必須提供自己的加鎖機(jī)制以保證這些復(fù)合操作都是原子操作,除非整個(gè)復(fù)合操作都可以委托給狀態(tài)變量殿雪。

4.3.4 發(fā)布底層的狀態(tài)變量

如果一個(gè)狀態(tài)變量是線程安全的暇咆,并且沒有任何不變性條件來約束它的值,在變量的操作上也不存在任何不允許的狀態(tài)轉(zhuǎn)換丙曙,那么就可以安全地發(fā)布這個(gè)變量爸业。

4.3.5 示例:發(fā)布狀態(tài)的車輛追蹤器


4.4 在現(xiàn)有的線程安全類中添加功能

直接修改原始的類;
擴(kuò)展原始類

  • 擴(kuò)展方法更加脆弱】髁現(xiàn)在同步策略被分布到多個(gè)單獨(dú)維護(hù)的源代碼文件中扯旷,如果底層的類改變了同步策略并選擇了不同的鎖來保護(hù)它的狀態(tài)變量,那么子類會(huì)被破壞索抓。

4.4.1 客戶端加鎖機(jī)制

第三種策略:擴(kuò)展類的功能

  • 將擴(kuò)展代碼放入一個(gè)“輔助類”中

相比擴(kuò)展钧忽,客戶端加鎖更加脆弱。它將類C的加鎖代碼放到與C完全無關(guān)的其他類中逼肯。

4.4.2 組合

通過類似委托的方式來實(shí)現(xiàn)


額外的同步層可能導(dǎo)致輕微的性能損失耸黑,但更為健壯。

4.5 將同步策略文檔化

在文檔中說明客戶代碼需要了解的線程安全性保證篮幢,以及代碼維護(hù)人員需要了解的同步策略大刊。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市三椿,隨后出現(xiàn)的幾起案子缺菌,更是在濱河造成了極大的恐慌葫辐,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件男翰,死亡現(xiàn)場離奇詭異另患,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蛾绎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進(jìn)店門昆箕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人租冠,你說我怎么就攤上這事鹏倘。” “怎么了顽爹?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵纤泵,是天一觀的道長。 經(jīng)常有香客問我镜粤,道長捏题,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任肉渴,我火速辦了婚禮公荧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘同规。我一直安慰自己循狰,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布券勺。 她就那樣靜靜地躺著绪钥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪关炼。 梳的紋絲不亂的頭發(fā)上程腹,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天,我揣著相機(jī)與錄音盗扒,去河邊找鬼跪楞。 笑死,一個(gè)胖子當(dāng)著我的面吹牛侣灶,可吹牛的內(nèi)容都是我干的甸祭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼褥影,長吁一口氣:“原來是場噩夢啊……” “哼池户!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤校焦,失蹤者是張志新(化名)和其女友劉穎赊抖,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體寨典,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡氛雪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了耸成。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片报亩。...
    茶點(diǎn)故事閱讀 40,133評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖井氢,靈堂內(nèi)的尸體忽然破棺而出弦追,到底是詐尸還是另有隱情,我是刑警寧澤花竞,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布劲件,位于F島的核電站,受9級特大地震影響约急,放射性物質(zhì)發(fā)生泄漏零远。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一厌蔽、第九天 我趴在偏房一處隱蔽的房頂上張望遍烦。 院中可真熱鬧,春花似錦躺枕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至近她,卻和暖如春叉瘩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背粘捎。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工薇缅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人攒磨。 一個(gè)月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓泳桦,卻偏偏與公主長得像,于是被迫代替她去往敵國和親娩缰。 傳聞我的和親對象是個(gè)殘疾皇子灸撰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評論 2 355

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