<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    xylz,imxylz

    關(guān)注后端架構(gòu)、中間件、分布式和并發(fā)編程

       :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      111 隨筆 :: 10 文章 :: 2680 評論 :: 0 Trackbacks

    07 2010 檔案

         摘要:
    在Set中有一個排序的集合SortedSet,用來保存按照自然順序排列的對象。Queue中同樣引入了一個支持排序的FIFO模型。
    并發(fā)隊列與Queue簡介 中介紹了,PriorityQueue和PriorityBlockingQueue就是支持排序的Queue。顯然一個支持阻塞的排序Queue要比一個非線程安全的Queue實現(xiàn)起來要復(fù)雜的多,因此下面只介紹PriorityBlockingQueue,至于PriorityQueue只需要去掉Blocking功能就基本相同了。  閱讀全文
    posted @ 2010-07-30 16:15 imxylz 閱讀(14134) | 評論 (0)  編輯

         摘要: 在上一節(jié)中詳細(xì)分析了LinkedBlockingQueue 的實現(xiàn)原理。實現(xiàn)一個可擴(kuò)展的隊列通常有兩種方式:一種方式就像LinkedBlockingQueue一樣使用鏈表,也就是每一個元素帶有下一個元素的引用,這樣的隊列原生就是可擴(kuò)展的;另外一種就是通過數(shù)組實現(xiàn),一旦隊列的大小達(dá)到數(shù)組的容量的時候就將數(shù)組擴(kuò)充一倍(或者一定的系數(shù)倍),從而達(dá)到擴(kuò)容的目的。常見的ArrayList就屬于第二種。前面章節(jié)介紹過的HashMap確是綜合使用了這兩種方式。
    對于一個Queue而言,同樣可以使用數(shù)組實現(xiàn)。使用數(shù)組的好處在于各個元素之間原生就是通過數(shù)組的索引關(guān)聯(lián)起來的,一次元素之間就是有序的,在通過索引操作數(shù)組就方便多了。當(dāng)然也有它不利的一面,擴(kuò)容起來比較麻煩,同時刪除一個元素也比較低效。
    ArrayBlockingQueue 就是Queue的一種數(shù)組實現(xiàn)。  閱讀全文
    posted @ 2010-07-27 22:04 imxylz 閱讀(12937) | 評論 (0)  編輯

         摘要: 在《并發(fā)容器 part 4 并發(fā)隊列與Queue簡介》節(jié)中的類圖中可以看到,對于Queue來說,BlockingQueue是主要的線程安全版本。這是一個可阻塞的版本,也就是允許添加/刪除元素被阻塞,直到成功為止。
    BlockingQueue相對于Queue而言增加了兩個操作:put/take。下面是一張整理的表格。  閱讀全文
    posted @ 2010-07-24 00:02 imxylz 閱讀(19641) | 評論 (6)  編輯

         摘要: ConcurrentLinkedQueue是Queue的一個線程安全實現(xiàn)。先來看一段文檔說明。
    一個基于鏈接節(jié)點(diǎn)的無界線程安全隊列。此隊列按照 FIFO(先進(jìn)先出)原則對元素進(jìn)行排序。隊列的頭部 是隊列中時間最長的元素。隊列的尾部 是隊列中時間最短的元素。新的元素插入到隊列的尾部,隊列獲取操作從隊列頭部獲得元素。當(dāng)多個線程共享訪問一個公共 collection 時,ConcurrentLinkedQueue 是一個恰當(dāng)?shù)倪x擇。此隊列不允許使用 null 元素。

    由于ConcurrentLinkedQueue只是簡單的實現(xiàn)了一個隊列Queue,因此從API的角度講,沒有多少值的介紹,使用起來也很簡單,和前面遇到的所有FIFO隊列都類似。出隊列只能操作頭節(jié)點(diǎn),入隊列只能操作尾節(jié)點(diǎn),任意節(jié)點(diǎn)操作就需要遍歷完整的隊列。
    重點(diǎn)放在解釋ConcurrentLinkedQueue的原理和實現(xiàn)上。  閱讀全文
    posted @ 2010-07-23 14:11 imxylz 閱讀(20016) | 評論 (2)  編輯

         摘要: Queue是JDK 5以后引入的新的集合類,它屬于Java Collections Framework的成員,在Collection集合中和List/Set是同一級別的接口。通常來講Queue描述的是一種FIFO的隊列,當(dāng)然不全都是,比如PriorityQueue是按照優(yōu)先級的順序(或者說是自然順序,借助于Comparator接口)。
    下圖描述了Java Collections Framework中Queue的整個家族體系。
    對于Queue而言是在Collection的基礎(chǔ)上增加了offer/remove/poll/element/peek方法,另外重新定義了add方法。對于這六個方法,有不同的定義。  閱讀全文
    posted @ 2010-07-21 12:21 imxylz 閱讀(21453) | 評論 (5)  編輯

         摘要: 在上一篇中介紹了HashMap的原理,這一節(jié)是ConcurrentMap的最后一節(jié),所以會完整的介紹ConcurrentHashMap的實現(xiàn)。

    ConcurrentHashMap原理

    在讀寫鎖章節(jié)部分介紹過一種是用讀寫鎖實現(xiàn)Map的方法。此種方法看起來可以實現(xiàn)Map響應(yīng)的功能,而且吞吐量也應(yīng)該不錯。但是通過前面對讀寫鎖原理的分析后知道,讀寫鎖的適合場景是讀操作>>寫操作,也就是讀操作應(yīng)該占據(jù)大部分操作,另外讀寫鎖存在一個很嚴(yán)重的問題是讀寫操作不能同時發(fā)生。要想解決讀寫同時進(jìn)行問題(至少不同元素的讀寫分離),那么就只能將鎖拆分,不同的元素?fù)碛胁煌逆i,這種技術(shù)就是“鎖分離”技術(shù)。
    默認(rèn)情況下ConcurrentHashMap是用了16個類似HashMap 的結(jié)構(gòu),其中每一個HashMap擁有一個獨(dú)占鎖。也就是說最終的效果就是通過某種Hash算法,將任何一個元素均勻的映射到某個HashMap的Map.Entry上面,而對某個一個元素的操作就集中在其分布的HashMap上,與其它HashMap無關(guān)。這樣就支持最多16個并發(fā)的寫操作。  閱讀全文
    posted @ 2010-07-20 17:48 imxylz 閱讀(21013) | 評論 (9)  編輯

         摘要: 本來想比較全面和深入的談?wù)凜oncurrentHashMap的,發(fā)現(xiàn)網(wǎng)上有很多對HashMap和ConcurrentHashMap分析的文章,因此本小節(jié)盡可能的分析其中的細(xì)節(jié),少一點(diǎn)理論的東西,多談?wù)剝?nèi)部設(shè)計的原理和思想。
    要談ConcurrentHashMap的構(gòu)造,就不得不談HashMap的構(gòu)造,因此先從HashMap開始簡單介紹。

    HashMap原理
    我們從頭開始設(shè)想。要將對象存放在一起,如何設(shè)計這個容器。目前只有兩條路可以走,一種是采用分格技術(shù),每一個對象存放于一個格子中,這樣通過對格子的編號就能取到或者遍歷對象;另一種技術(shù)就是采用串聯(lián)的方式,將各個對象串聯(lián)起來,這需要各個對象至少帶有下一個對象的索引(或者指針)。顯然第一種就是數(shù)組的概念,第二種就是鏈表的概念。所有的容器的實現(xiàn)其實都是基于這兩種方式的,不管是數(shù)組還是鏈表,或者二者俱有。HashMap采用的就是數(shù)組的方式。
    有了存取對象的容器后還需要以下兩個條件才能完成Map所需要的條件。  閱讀全文
    posted @ 2010-07-20 00:22 imxylz 閱讀(22910) | 評論 (3)  編輯

         摘要: 從這一節(jié)開始正式進(jìn)入并發(fā)容器的部分,來看看JDK 6帶來了哪些并發(fā)容器。
    在JDK 1.4以下只有Vector和Hashtable是線程安全的集合(也稱并發(fā)容器,Collections.synchronized*系列也可以看作是線程安全的實現(xiàn))。從JDK 5開始增加了線程安全的Map接口ConcurrentMap和線程安全的隊列BlockingQueue(盡管Queue也是同時期引入的新的集合,但是規(guī)范并沒有規(guī)定一定是線程安全的,事實上一些實現(xiàn)也不是線程安全的,比如PriorityQueue、ArrayDeque、LinkedList等,在Queue章節(jié)中會具體討論這些隊列的結(jié)構(gòu)圖和實現(xiàn))。

    在介紹ConcurrencyMap之前先來回顧下Map的體系結(jié)構(gòu)。下圖描述了Map的體系結(jié)構(gòu),其中藍(lán)色字體的是JDK 5以后新增的并發(fā)容器。  閱讀全文
    posted @ 2010-07-19 15:25 imxylz 閱讀(24631) | 評論 (8)  編輯

    posted @ 2010-07-16 11:59 imxylz 閱讀(9033) | 評論 (4)  編輯

         摘要:
    主要談?wù)勬i的性能以及其它一些理論知識,內(nèi)容主要的出處是《Java Concurrency in Practice》,結(jié)合自己的理解和實際應(yīng)用對鎖機(jī)制進(jìn)行一個小小的總結(jié)。

    首先需要強(qiáng)調(diào)的一點(diǎn)是:所有鎖(包括內(nèi)置鎖和高級鎖)都是有性能消耗的,也就是說在高并發(fā)的情況下,由于鎖機(jī)制帶來的上下文切換、資源同步等消耗是非常可觀的。在某些極端情況下,線程在鎖上的消耗可能比線程本身的消耗還要多。所以如果可能的話,在任何情況下都盡量少用鎖,如果不可避免那么采用非阻塞算法是一個不錯的解決方案,但是卻也不是絕對的。  閱讀全文
    posted @ 2010-07-16 00:15 imxylz 閱讀(16575) | 評論 (2)  編輯

         摘要:
    這一節(jié)主要是談?wù)勛x寫鎖的實現(xiàn)。
    上一節(jié)中提到,ReadWriteLock看起來有兩個鎖:readLock/writeLock。如果真的是兩個鎖的話,它們之間又是如何相互影響的呢?
    事實上在ReentrantReadWriteLock里鎖的實現(xiàn)是靠java.util.concurrent.locks.ReentrantReadWriteLock.Sync完成的。這個類看起來比較眼熟,實際上它是AQS的一個子類,這中類似的結(jié)構(gòu)在CountDownLatch、ReentrantLock、Semaphore里面都存在。同樣它也有兩種實現(xiàn):公平鎖和非公平鎖,也就是java.util.concurrent.locks.ReentrantReadWriteLock.FairSync和java.util.concurrent.locks.ReentrantReadWriteLock.NonfairSync。這里暫且不提。
    在ReentrantReadWriteLock里面的鎖主體就是一個Sync,也就是上面提到的FairSync或者NonfairSync,所以說實際  閱讀全文
    posted @ 2010-07-15 00:41 imxylz 閱讀(20308) | 評論 (1)  編輯

         摘要: 從這一節(jié)開始介紹鎖里面的最后一個工具:讀寫鎖(ReadWriteLock)。
    ReentrantLock 實現(xiàn)了標(biāo)準(zhǔn)的互斥操作,也就是一次只能有一個線程持有鎖,也即所謂獨(dú)占鎖的概念。前面的章節(jié)中一直在強(qiáng)調(diào)這個特點(diǎn)。顯然這個特點(diǎn)在一定程度上面減低了吞吐量,實際上獨(dú)占鎖是一種保守的鎖策略,在這種情況下任何“讀/讀”,“寫/讀”,“寫/寫”操作都不能同時發(fā)生。但是同樣需要強(qiáng)調(diào)的一個概念是,鎖是有一定的開銷的,當(dāng)并發(fā)比較大的時候,鎖的開銷就比較客觀了。所以如果可能的話就盡量少用鎖,非要用鎖的話就嘗試看能否改造為讀寫鎖。
    ReadWriteLock描述的是:一個資源能夠被多個讀線程訪問,或者被一個寫線程訪問,但是不能同時存在讀寫線程。也就是說讀寫鎖使用的場合是一個共享資源被大量讀取操作,而只有少量的寫操作(修改數(shù)據(jù))。清單1描述了ReadWriteLock的API。  閱讀全文
    posted @ 2010-07-14 14:18 imxylz 閱讀(24252) | 評論 (4)  編輯

         摘要: Semaphore 是一個計數(shù)信號量。從概念上講,信號量維護(hù)了一個許可集。如有必要,在許可可用前會阻塞每一個 acquire(),然后再獲取該許可。每個 release() 添加一個許可,從而可能釋放一個正在阻塞的獲取者。但是,不使用實際的許可對象,Semaphore 只對可用許可的號碼進(jìn)行計數(shù),并采取相應(yīng)的行動。
    說白了,Semaphore是一個計數(shù)器,在計數(shù)器不為0的時候?qū)€程就放行,一旦達(dá)到0,那么所有請求資源的新線程都會被阻塞,包括增加請求到許可的線程,也就是說Semaphore不是可重入的。每一次請求一個許可都會導(dǎo)致計數(shù)器減少1,同樣每次釋放一個許可都會導(dǎo)致計數(shù)器增加1,一旦達(dá)到了0,新的許可請求線程將被掛起。
    緩存池整好使用此思想來實現(xiàn)的,比如鏈接池、對象池等。  閱讀全文
    posted @ 2010-07-13 22:41 imxylz 閱讀(23366) | 評論 (2)  編輯

         摘要:
    如果說CountDownLatch是一次性的,那么CyclicBarrier正好可以循環(huán)使用。它允許一組線程互相等待,直到到達(dá)某個公共屏障點(diǎn) (common barrier point)。所謂屏障點(diǎn)就是一組任務(wù)執(zhí)行完畢的時刻。
      閱讀全文
    posted @ 2010-07-12 23:33 imxylz 閱讀(22377) | 評論 (2)  編輯

         摘要: 此小節(jié)介紹幾個與鎖有關(guān)的有用工具。
    閉鎖(Latch)
    閉鎖(Latch):一種同步方法,可以延遲線程的進(jìn)度直到線程到達(dá)某個終點(diǎn)狀態(tài)。通俗的講就是,一個閉鎖相當(dāng)于一扇大門,在大門打開之前所有線程都被阻斷,一旦大門打開所有線程都將通過,但是一旦大門打開,所有線程都通過了,那么這個閉鎖的狀態(tài)就失效了,門的狀態(tài)也就不能變了,只能是打開狀態(tài)。也就是說閉鎖的狀態(tài)是一次性的,它確保在閉鎖打開之前所有特定的活動都需要在閉鎖打開之后才能完成。
    CountDownLatch是JDK 5+里面閉鎖的一個實現(xiàn),允許一個或者多個線程等待某個事件的發(fā)生。CountDownLatch有一個正數(shù)計數(shù)器,countDown方法對計數(shù)器做減操作,await方法等待計數(shù)器達(dá)到0。所有await的線程都會阻塞直到計數(shù)器為0或者等待線程中斷或者超時。  閱讀全文
    posted @ 2010-07-09 09:21 imxylz 閱讀(29328) | 評論 (6)  編輯

         摘要: 這是一份完整的Java 并發(fā)整理筆記,記錄了我最近幾年學(xué)習(xí)Java并發(fā)的一些心得和體會。  閱讀全文
    posted @ 2010-07-08 19:17 imxylz 閱讀(168183) | 評論 (43)  編輯

         摘要: 本小節(jié)介紹鎖釋放Lock.unlock()。
    Release/TryRelease
    unlock操作實際上就調(diào)用了AQS的release操作,釋放持有的鎖。  閱讀全文
    posted @ 2010-07-08 12:33 imxylz 閱讀(30485) | 評論 (11)  編輯

         摘要: 接上篇,這篇從Lock.lock/unlock開始。特別說明在沒有特殊情況下所有程序、API、文檔都是基于JDK 6.0的。
    在沒有深入了解內(nèi)部機(jī)制及實現(xiàn)之前,先了解下為什么會存在公平鎖和非公平鎖。公平鎖保證一個阻塞的線程最終能夠獲得鎖,因為是有序的,所以總是可以按照請求的順序獲得鎖。不公平鎖意味著后請求鎖的線程可能在其前面排列的休眠線程恢復(fù)前拿到鎖,這樣就有可能提高并發(fā)的性能。這是因為通常情況下掛起的線程重新開始與它真正開始運(yùn)行,二者之間會產(chǎn)生嚴(yán)重的延時。因此非公平鎖就可以利用這段時間完成操作。這是非公平鎖在某些時候比公平鎖性能要好的原因之一。  閱讀全文
    posted @ 2010-07-07 00:05 imxylz 閱讀(40166) | 評論 (6)  編輯

         摘要: 在理解J.U.C原理以及鎖機(jī)制之前,我們來介紹J.U.C框架最核心也是最復(fù)雜的一個基礎(chǔ)類:java.util.concurrent.locks.AbstractQueuedSynchronizer。

    AQS
    AbstractQueuedSynchronizer,簡稱AQS,是J.U.C最復(fù)雜的一個類,導(dǎo)致絕大多數(shù)講解并發(fā)原理或者實戰(zhàn)的時候都不會提到此類。但是虛心的作者愿意借助自己有限的能力和精力來探討一二(參考資源中也有一些作者做了部分的分析。)。
    首先從理論知識開始,在了解了相關(guān)原理后會針對源碼進(jìn)行一些分析,最后加上一些實戰(zhàn)來描述。  閱讀全文
    posted @ 2010-07-06 18:29 imxylz 閱讀(53043) | 評論 (3)  編輯

         摘要: 前面的章節(jié)主要談?wù)勗硬僮?,至于與原子操作一些相關(guān)的問題或者說陷阱就放到最后的總結(jié)篇來整體說明。從這一章開始花少量的篇幅談?wù)勬i機(jī)制。
    上一個章節(jié)中談到了鎖機(jī)制,并且針對于原子操作談了一些相關(guān)的概念和設(shè)計思想。接下來的文章中,盡可能的深入研究鎖機(jī)制,并且理解里面的原理和實際應(yīng)用場合。
    盡管synchronized在語法上已經(jīng)足夠簡單了,在JDK 5之前只能借助此實現(xiàn),但是由于是獨(dú)占鎖,性能卻不高,因此JDK 5以后就開始借助于JNI來完成更高級的鎖實現(xiàn)。
    JDK 5中的鎖是接口java.util.concurrent.locks.Lock。另外java.util.concurrent.locks.ReadWriteLock提供了一對可供讀寫并發(fā)的鎖。根據(jù)前面的規(guī)則,我們從java.util.concurrent.locks.Lock的API開始。  閱讀全文
    posted @ 2010-07-05 13:37 imxylz 閱讀(42225) | 評論 (11)  編輯

         摘要: 在JDK 5之前Java語言是靠synchronized關(guān)鍵字保證同步的,這會導(dǎo)致有鎖(后面的章節(jié)還會談到鎖)。
    鎖機(jī)制存在以下問題:
    (1)在多線程競爭下,加鎖、釋放鎖會導(dǎo)致比較多的上下文切換和調(diào)度延時,引起性能問題。
    (2)一個線程持有鎖會導(dǎo)致其它所有需要此鎖的線程掛起。
    (3)如果一個優(yōu)先級高的線程等待一個優(yōu)先級低的線程釋放鎖會導(dǎo)致優(yōu)先級倒置,引起性能風(fēng)險。
    volatile是不錯的機(jī)制,但是volatile不能保證原子性。因此對于同步最終還是要回到鎖機(jī)制上來。
    獨(dú)占鎖是一種悲觀鎖,synchronized就是一種獨(dú)占鎖,會導(dǎo)致其它所有需要鎖的線程掛起,等待持有鎖的線程釋放鎖。而另一個更加有效的鎖就是樂觀鎖。所謂樂觀鎖就是,每次不加鎖而是假設(shè)沒有沖突而去完成某項操作,如果因為沖突失敗就重試,直到成功為止。  閱讀全文
    posted @ 2010-07-04 18:03 imxylz 閱讀(48006) | 評論 (19)  編輯

         摘要: 在這個小結(jié)里面重點(diǎn)討論原子操作的原理和設(shè)計思想。
    由于在下一個章節(jié)中會談到鎖機(jī)制,因此此小節(jié)中會適當(dāng)引入鎖的概念。
    在Java Concurrency in Practice中是這樣定義線程安全的:
    當(dāng)多個線程訪問一個類時,如果不用考慮這些線程在運(yùn)行時環(huán)境下的調(diào)度和交替運(yùn)行,并且不需要額外的同步及在調(diào)用方代碼不必做其他的協(xié)調(diào),這個類的行為仍然是正確的,那么這個類就是線程安全的。  閱讀全文
    posted @ 2010-07-03 20:40 imxylz 閱讀(46607) | 評論 (16)  編輯

         摘要: 在這一部分開始討論數(shù)組原子操作和一些其他的原子操作。
    AtomicIntegerArray/AtomicLongArray/AtomicReferenceArray的API類似,選擇有代表性的AtomicIntegerArray來描述這些問題。
    int get(int i)
    獲取位置 i 的當(dāng)前值。很顯然,由于這個是數(shù)組操作,就有索引越界的問題(IndexOutOfBoundsException異常)。

    對于下面的API起始和AtomicInteger是類似的,這種通過方法、參數(shù)的名稱就能夠得到函數(shù)意義的寫法是非常值得稱贊的。在《重構(gòu):改善既有代碼的設(shè)計》和《代碼整潔之道》中都非常推崇這種做法。  閱讀全文
    posted @ 2010-07-02 14:19 imxylz 閱讀(48169) | 評論 (6)  編輯

         摘要: 從相對簡單的Atomic入手(java.util.concurrent是基于Queue的并發(fā)包,而Queue,很多情況下使用到了Atomic操作,因此首先從這里開始)。很多情況下我們只是需要一個簡單的、高效的、線程安全的遞增遞減方案。注意,這里有三個條件:簡單,意味著程序員盡可能少的操作底層或者實現(xiàn)起來要比較容易;高效意味著耗用資源要少,程序處理速度要快;線程安全也非常重要,這個在多線程下能保證數(shù)據(jù)的正確性。這三個條件看起來比較簡單,但是實現(xiàn)起來卻難以令人滿意。
    通常情況下,在Java里面,++i或者--i不是線程安全的,這里面有三個獨(dú)立的操作:或者變量當(dāng)前值,為該值+1/-1,然后寫回新的值。在沒有額外資源可以利用的情況下,只能使用加鎖才能保證讀-改-寫這三個操作時“原子性”的。  閱讀全文
    posted @ 2010-07-01 15:21 imxylz 閱讀(65852) | 評論 (2)  編輯


    ©2009-2014 IMXYLZ
    主站蜘蛛池模板: 亚洲大香人伊一本线| 最近最好最新2019中文字幕免费| 亚洲熟妇无码久久精品| 国产成人精品曰本亚洲79ren| 毛片免费全部播放一级| 8090在线观看免费观看| 国产线视频精品免费观看视频| 校园亚洲春色另类小说合集| 亚洲乱码一区av春药高潮| 77777_亚洲午夜久久多人| 亚洲国产精品无码久久一区二区| 亚洲а∨天堂久久精品| 日本高清免费网站| 夜夜嘿视频免费看| 噼里啪啦电影在线观看免费高清| 99久久免费中文字幕精品| 十八禁在线观看视频播放免费| 久青草国产免费观看| 成年网在线观看免费观看网址| 亚洲av日韩专区在线观看| 亚洲中文无码mv| 亚洲永久在线观看| 亚洲欧洲另类春色校园网站| 亚洲综合激情九月婷婷| 久久国产亚洲高清观看| 亚洲精品免费在线视频| 亚洲综合小说久久另类区| 亚洲美女aⅴ久久久91| 亚洲男人的天堂在线| 亚洲婷婷在线视频| 亚洲一区二区三区国产精品无码| 亚洲成人免费网站| 亚洲乱码在线卡一卡二卡新区| 香蕉大伊亚洲人在线观看| 亚洲中文字幕久久精品蜜桃| 亚洲国产成人久久精品软件| 欧洲亚洲综合一区二区三区| 免费一级毛suv好看的国产网站 | 国产在线国偷精品免费看| 国产偷伦视频免费观看| 99久热只有精品视频免费看|