小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

java并發(fā)編程實(shí)踐筆記

 hehffyy 2011-11-27

1, 保證線程安全的三種方法 :
a, 不要跨線程訪問(wèn)共享變量
b, 使共享變量是 final類(lèi)型的
c, 將共享變量的操作加上同步

2, 一開(kāi)始就將類(lèi)設(shè)計(jì)成線程安全的 , 比在后期重新修復(fù)它 ,更容易 .

3, 編寫(xiě)多線程程序 , 首先保證它是正確的 , 其次再考慮性能 .

4, 無(wú)狀態(tài)或只讀對(duì)象永遠(yuǎn)是線程安全的 .

5, 不要將一個(gè)共享變量裸露在多線程環(huán)境下 (無(wú)同步或不可變性保護(hù) )

6, 多線程環(huán)境下的延遲加載需要同步的保護(hù) , 因?yàn)檠舆t加載會(huì)造成對(duì)象重復(fù)實(shí)例化

7, 對(duì)于 volatile 聲明的數(shù)值類(lèi)型變量進(jìn)行運(yùn)算 , 往往是不安全的 (volatile 只能保證可見(jiàn)性 , 不能保證原子性 ).
詳見(jiàn) volatile 原理與技巧中 , 臟數(shù)據(jù)問(wèn)題討論 .

8, 當(dāng)一個(gè)線程請(qǐng)求獲得它自己占有的鎖時(shí) ( 同一把鎖的嵌套使用 ), 我們稱(chēng)該鎖為可重入鎖 .
在 jdk1.5 并發(fā)包中 , 提供了可重入鎖的 java 實(shí)現(xiàn) -ReentrantLock.

9, 每個(gè)共享變量 , 都應(yīng)該由一個(gè)唯一確定的鎖保護(hù) .
創(chuàng)建與變量相同數(shù)目的 ReentrantLock, 使他們負(fù)責(zé)每個(gè)變量的線程安全 .

10,雖然縮小同步塊的范圍 , 可以提升系統(tǒng)性能 .
但在保證原子性的情況下 , 不可將原子操作分解成多個(gè) synchronized塊 .

11, 在沒(méi)有同步的情況下 , 編譯器與處理器運(yùn)行時(shí)的指令執(zhí)行順序可能完全出乎意料 .
原因是 , 編譯器或處理器為了優(yōu)化自身執(zhí)行效率 , 而對(duì)指令進(jìn)行了的重排序 (reordering).

12, 當(dāng)一個(gè)線程在沒(méi)有同步的情況下讀取變量 , 它可能會(huì)得到一個(gè)過(guò)期值 , 但是至少它可以看到那個(gè)
線程在當(dāng)時(shí)設(shè)定的一個(gè)真實(shí)數(shù)值 . 而不是憑空而來(lái)的值 . 這種安全保證 , 稱(chēng)之為 最低限的安全性 (out-of-thin-air safety)

在開(kāi)發(fā)并發(fā)應(yīng)用程序時(shí) , 有時(shí)為了大幅度提高系統(tǒng)的吞吐量與性能 , 會(huì)采用這種無(wú)保障的做法 .
但是針對(duì) , 數(shù)值的運(yùn)算 , 仍舊是被否決的 .

13, volatile 變量 , 只能保證可見(jiàn)性 , 無(wú)法保證原子性 .

14, 某些耗時(shí)較長(zhǎng)的網(wǎng)絡(luò)操作或 IO, 確保執(zhí)行時(shí) , 不要占有鎖 .

15, 發(fā)布 (publish) 對(duì)象 , 指的是使它能夠被當(dāng)前范圍之外的代碼所使用 .( 引用傳遞 )
對(duì)象逸出 (escape), 指的是一個(gè)對(duì)象在尚未準(zhǔn)備好時(shí)將它發(fā)布 .

原則 : 為防止逸出 , 對(duì)象必須要被完全構(gòu)造完后 , 才可以被發(fā)布 ( 最好的解決方式是采用同步 )

this 關(guān)鍵字引用對(duì)象逸出
例子 : 在構(gòu)造函數(shù)中 , 開(kāi)啟線程 , 并將自身對(duì)象 this 傳入線程 , 造成引用傳遞 .
而此時(shí) , 構(gòu)造函數(shù)尚未執(zhí)行完 , 就會(huì)發(fā)生對(duì)象逸出了 .

16, 必要時(shí) , 使用 ThreadLocal變量確保線程封閉性 (封閉線程往往是比較安全的 , 但一定程度上會(huì)造成性能損耗 )
封閉對(duì)象的例子在實(shí)際使用過(guò)程中 , 比較常見(jiàn) , 例如 hibernate openSessionInView機(jī)制 , jdbc的 connection機(jī)制 .

17, 單一不可變對(duì)象往往是線程安全的 (復(fù)雜不可變對(duì)象需要保證其內(nèi)部成員變量也是不可變的 )
良好的多線程編程習(xí)慣是 : 將所有的域都聲明為 final, 除非它們是可變的

18, 保證共享變量的發(fā)布是安全的 
a, 通過(guò)靜態(tài)初始化器初始化對(duì)象 (jls 12.4.2 敘述 , jvm 會(huì)保證靜態(tài)初始化變量是同步的 )
b, 將對(duì)象申明為 volatile 或使用 AtomicReference
c, 保證對(duì)象是不可變的
d, 將引用或可變操作都由鎖來(lái)保護(hù)

19, 設(shè)計(jì)線程安全的類(lèi) , 應(yīng)該包括的基本要素 :
a, 確定哪些是可變共享變量
b, 確定哪些是不可變的變量
c, 指定一個(gè)管理并發(fā)訪問(wèn)對(duì)象狀態(tài)的策略

20, 將數(shù)據(jù)封裝在對(duì)象內(nèi)部 , 并保證對(duì)數(shù)據(jù)的訪問(wèn)是原子的 .
建議采用 volatile javabean 模型或者構(gòu)造同步的 getter,setter.

21, 線程限制性使構(gòu)造線程安全的類(lèi)變得更容易 , 因?yàn)轭?lèi)的狀態(tài)被限制后 , 分析它的線程安全性時(shí) , 就不必檢查完整的程序 .

22, 編寫(xiě)并發(fā)程序 , 需要更全的注釋 , 更完整的文檔說(shuō)明 .

23, 在需要細(xì)分鎖的分配時(shí) , 使用 java監(jiān)視器模式好于使用自身對(duì)象的監(jiān)視器鎖 .
前者的靈活性更好 .

Object target = new Object();
// 這里使用外部對(duì)象來(lái)作為監(jiān)視器 , 而非 this
synchronized(target) {
// TODO
}

針對(duì) java monitor pattern, 實(shí)際上 ReentrantLock的實(shí)現(xiàn)更易于并發(fā)編程 .
功能上 , 也更強(qiáng)大 .

24, 設(shè)計(jì)并發(fā)程序時(shí) , 在保證伸縮性與性能折中的前提下 , 優(yōu)先考慮將共享變量委托給線程安全的類(lèi) .
由它來(lái)控制全局的并發(fā)訪問(wèn) .

25, 使用普通同步容器 (Vector, Hashtable) 的迭代器 , 需要外部鎖來(lái)保證其原子性 .
原因是 , 普通同步容器產(chǎn)生的迭代器是非線程安全的 .

26, 在并發(fā)編程中 , 需要容器支持的時(shí)候 , 優(yōu)先考慮使用 jdk 并發(fā)容器 

(ConcurrentHashMap, ConcurrentLinkedQueue, CopyOnWriteArrayList…).

27, ConcurrentHashMap, CopyOnWriteArrayList
并發(fā)容器的迭代器 , 以及全范圍的 size(), isEmpty() 都表現(xiàn)出弱一致性 .
他們只能標(biāo)示容器當(dāng)時(shí)的一個(gè)數(shù)據(jù)狀態(tài) . 無(wú)法完整響應(yīng)容器之后的變化和修改 .

28, 使用有界隊(duì)列 , 在隊(duì)列充滿(mǎn)或?yàn)榭諘r(shí) , 阻塞所有的讀與寫(xiě)操作 . ( 實(shí)現(xiàn)生產(chǎn) – 消費(fèi)的良好方案 )
BlockQueue 下的實(shí)現(xiàn)有 LinkedBlockingQueue 與 ArrayBlockingQueue, 前者為鏈表 , 可變操作頻繁優(yōu)先考慮 , 后者為數(shù)組 , 讀取操作頻繁優(yōu)先考慮 .
PriorityBlockingQueue 是一個(gè)按優(yōu)先級(jí)順序排列的阻塞隊(duì)列 , 它可以對(duì)所有置入的元素進(jìn)行排序 ( 實(shí)現(xiàn) Comparator 接口 )

29, 當(dāng)一個(gè)方法 , 能拋出 InterruptedException, 則意味著 , 這個(gè)方法是一個(gè)可阻塞的方法 , 如果它被中斷 , 將提前結(jié)束阻塞狀態(tài) .
當(dāng)你調(diào)用一個(gè)阻塞方法 , 也就意味著 , 本身也稱(chēng)為了一個(gè)阻塞方法 , 因?yàn)槟惚仨毜却枞椒ǚ祷?.

如果阻塞方法拋出了中斷異常 , 我們需要做的是 , 將其往上層拋 , 除非當(dāng)前已經(jīng)是需要捕獲異常的層次 .
如果當(dāng)前方法 , 不能拋出 InterruptedException, 可以使用 Thread.currentThread.interrupt() 方法 , 手動(dòng)進(jìn)行中斷 .

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多