(1)核心在于管理:
在構(gòu)建穩(wěn)健的并發(fā)程序時(shí),必須正確的使用線程和鎖。
但這些終歸只是一些機(jī)制钮糖。
要編寫線程安全的代碼,其核心在于要對(duì)狀態(tài)訪問操作進(jìn)行管理酌住,特別是對(duì)共享的和可變的狀態(tài)的訪問此衅。
如果從一開始就設(shè)計(jì)一個(gè)線程安全的類超陆,那么比在以后再將這個(gè)類修改為線程安全的類要容易的多。
(2)不變性條件和后驗(yàn)條件:
在許多類中,都定義了一些不變性條件最域,用于判斷狀態(tài)是有效的還是無效的。
同樣在操作中還會(huì)包含一些后驗(yàn)條件來判斷狀態(tài)遷移是否是有效的详民。
類的不變性條件與后驗(yàn)條件吁伺,約束了在對(duì)象上有哪些狀態(tài)和狀態(tài)轉(zhuǎn)換是有效的。
(3)線程安全性:
正確性的含義是欺矫,某個(gè)類的行為與其規(guī)范完全一致稠歉。
線程安全性:當(dāng)多個(gè)線程訪問某個(gè)類時(shí),這個(gè)類始終都能表現(xiàn)出正確的行為汇陆,那么稱這個(gè)類是線程安全的怒炸。
(4)競(jìng)態(tài)條件
在并發(fā)編程中,這種由于不恰當(dāng)?shù)膱?zhí)行時(shí)序而出現(xiàn)不正確的結(jié)果毡代,是一種非常重要的情況阅羹,稱為競(jìng)態(tài)條件。
當(dāng)某個(gè)計(jì)算的正確性取決于多個(gè)線程的交替執(zhí)行時(shí)序時(shí)教寂,那么就會(huì)發(fā)生競(jìng)態(tài)條件捏鱼。
換句話說,就是正確的結(jié)果要取決于運(yùn)氣酪耕。
觀察結(jié)果的失效就是大多數(shù)競(jìng)態(tài)條件的本質(zhì)导梆,基于一種可能失效的觀察結(jié)果,來做出判斷或者執(zhí)行某個(gè)計(jì)算。
要保持狀態(tài)的一致性看尼,就需要在單個(gè)原子操作中更新所有相關(guān)的狀態(tài)變量递鹉。
對(duì)于每個(gè)包含多個(gè)變量的不變性條件,其中涉及的所有變量都需要由同一個(gè)鎖來保護(hù)藏斩。
當(dāng)執(zhí)行時(shí)間較長(zhǎng)的計(jì)算躏结,或者,可能無法快速完成的操作時(shí)狰域,一定不要持有鎖媳拴。
(4)重排序:
重排序:在沒有同步的情況下,編譯器兆览,處理器以及運(yùn)行時(shí)等都可能對(duì)操作的執(zhí)行順序進(jìn)行一些意想不到的調(diào)整屈溉。在缺乏足夠同步的多線程程序中,要想對(duì)內(nèi)存操作的執(zhí)行順序進(jìn)行判斷抬探,幾乎無法得到正確的結(jié)論子巾。
當(dāng)把變量聲明為volatile類型后,編譯器與運(yùn)行時(shí)都會(huì)注意到這個(gè)變量是共享的驶睦,因此不會(huì)將該變量上的操作與其他內(nèi)存操作一起重排序砰左。
volatile變量不會(huì)被緩存在寄存器或者對(duì)其他處理器不可見的地方,因此在讀取volatile類型的變量時(shí)场航,總是會(huì)返回最新寫入的值缠导。
在訪問volatile變量時(shí),不會(huì)執(zhí)行加鎖操作溉痢,因此也就不會(huì)使執(zhí)行線程阻塞僻造,volatile變量是一種比sychronized關(guān)鍵字更輕量級(jí)的同步機(jī)制。
(5)加鎖與volatile:
加鎖機(jī)制孩饼,既可以確彼柘鳎可見性又可以確保原子性,而volatile變量只能確倍迫ⅲ可見性立膛。
當(dāng)且僅當(dāng)滿足以下所有條件時(shí),才應(yīng)該使用volatile變量:
(a)對(duì)變量的寫入操作不依賴變量的當(dāng)前值梯码,或者你能確保只有單個(gè)線程更新變量的值宝泵。
(b)該變量不會(huì)與其他狀態(tài)變量一起納入不變性條件中。
(c)在訪問變量時(shí)不需要加鎖轩娶。
(6)常用策略:
在并發(fā)程序中使用和共享對(duì)象時(shí)儿奶,可以使用一些實(shí)用的策略,包括:
線程封閉:線程封閉的對(duì)象只能由一個(gè)線程擁有鳄抒,對(duì)象被封閉在該線程中闯捎,并且只能由這個(gè)線程修改椰弊。
只讀共享:在沒有額外同步的情況下,共享的只讀對(duì)象可以由多個(gè)線程并發(fā)訪問瓤鼻,但任何線程都不能修改它秉版。共享的只讀對(duì)象包括不可變對(duì)象和事實(shí)不可變對(duì)象。
線程安全共享:線程安全的對(duì)象在其內(nèi)部實(shí)現(xiàn)同步娱仔,因此多個(gè)線程可以通過對(duì)象的公有接口來進(jìn)行訪問而不需要進(jìn)一步的同步沐飘。
保護(hù)對(duì)象:被保護(hù)的對(duì)象只能通過持有特定的鎖來訪問游桩。保護(hù)對(duì)象包括封裝在其他線程安全對(duì)象中的對(duì)象牲迫,以及已發(fā)布的并且由某個(gè)特定鎖保護(hù)的對(duì)象。
在設(shè)計(jì)線程安全類的過程中借卧,需要包含以下三個(gè)基本要素:
(a)找出構(gòu)成對(duì)象狀態(tài)的所有變量
(b)找出約束狀態(tài)變量的不變性條件
(c)建立對(duì)象狀態(tài)的并發(fā)訪問管理策略