併發容器 通過併發容器來替代同步容器,提供性能,可以極大地提高伸縮性並降低風險。 Java 5.0增加了兩種新的容器類型:Queue和BlockingQueue。Queue的實現有:ConcurrentLinkedQueue,這是一個傳統的先進先出的隊列,PriorityQueue(非併發的)優先隊 ...
併發容器
通過併發容器來替代同步容器,提供性能,可以極大地提高伸縮性並降低風險。
Java 5.0增加了兩種新的容器類型:Queue和BlockingQueue。Queue的實現有:ConcurrentLinkedQueue,這是一個傳統的先進先出的隊列,PriorityQueue(非併發的)優先隊列。Queue上的操作不會阻塞,如果隊列為空,獲取隊列元素的操作將返回空值。
BlockingQueue擴展了Queue,增加了可阻塞的插入和獲取操作。如果隊列為空獲取元素的操作,那麼獲取隊列元素的操作將一直阻塞,直到隊列出現一個可用的元素。如果隊列已滿(對於有界隊列來說),那麼插入元素的操作將一直阻塞,直到隊列中出現可用的空間。
ConcurrentHashMap與HashMap一樣也是基於散列的Map,但是它完全使用了不用的加鎖策略來提供更高的併發性和可伸縮性。ConcurrentHashMap並不是在每個方法上都使用同一個鎖來同步,而是使用了一種粒度更細的加鎖機制來實現更大程度的共用,也就是分段鎖。在這種機制中,任意數量的線程可以併發地訪問Map,執行讀取的線程和寫入的線程可以併發的進行,並且一定數量的寫入線程可以併發地修改Map。ConcurrentHashMap容器在迭代的時候不會拋出ConcurrentModificationException,因此不需要在迭代的過程加鎖。ConcurrentHashMap返回的迭代器具有弱一致性(Weakly Consistent),而並非“即使失敗”。弱一致性的迭代器可以容忍併發的修改,當創建迭代器時會遍歷所有的元素,並可以(但不保證)在迭代被構建後修改操作反應給容器。儘管這樣,任然還是有權衡的因素。對於需要在對整個Map進行計算的方法,例如size和isEmpty,這些方法的語義被略微減弱了以反應容器的併發特性。size在計算結果時可能已經過期了,它實際上是一個估計值,因此size返回的是一個近似值不是精確值。
額外的原子操作
ConcurrentHashMap不能被加鎖來進行獨占的訪問,因此我們無法使用客戶端加鎖來創建新的原子操作。這些複合操作都實現了原子操作,例如“若沒有則添加”,“若相對則移除(Remove-If-Equal)”和“若相等則替換(Replace-If-Equal)”等。
CopyOnWriteArrayList
CopyOnWriteArrayList用於替換同步List,在某些情況下提供了更好的併發性能。並且迭代期間不需要對容器進行加鎖或複製。“寫入時複製(Copy-On-Write)”容器的線程安全在於,只要正確的發佈一個事實的不可變對象,那麼訪問該對象就不需要加鎖同步。每次修改時,都會創建並重新發佈一個新的容器副本,從而實現可變性。“寫入時複製”容器迭代操作不會拋出ConcurrentModificationException,並且返回時的元素與迭代器創建時的元素完全一致,而不必考慮之後修改操作帶來的影響。“寫入時複製”容器修改操作需要一定的開銷,所以僅當迭代操作遠遠多於修改操作的時候,才應該使用它。