1. 程式人生 > >Java併發程式設計:併發容器之ConcurrentHashMap

Java併發程式設計:併發容器之ConcurrentHashMap

下面這部分內容轉載自:

  JDK5中添加了新的concurrent包,相對同步容器而言,併發容器通過一些機制改進了併發效能。因為同步容器將所有對容器狀態的訪問都

序列化了,這樣保證了執行緒的安全性,所以這種方法的代價就是嚴重降低了併發性,當多個執行緒競爭容器時,吞吐量嚴重降低。因此Java5.0開

始針對多執行緒併發訪問設計,提供了併發效能較好的併發容器,引入了java.util.concurrent包。與Vector和Hashtable、

Collections.synchronizedXxx()同步容器等相比,util.concurrent中引入的併發容器主要解決了兩個問題: 
1)根據具體場景進行設計,儘量避免synchronized,提供併發性。 
2)定義了一些併發安全的複合操作,並且保證併發環境下的迭代操作不會出錯。

  util.concurrent中容器在迭代時,可以不封裝在synchronized中,可以保證不拋異常,但是未必每次看到的都是"最新的、當前的"資料。

  下面是對併發容器的簡單介紹:

  ConcurrentHashMap代替同步的Map(Collections.synchronized(new HashMap())),眾所周知,HashMap是根據雜湊值分段儲存的,同步Map在同步的時候鎖住了所有的段,而ConcurrentHashMap加鎖的時候根據雜湊值鎖住了雜湊值鎖對應的那段,因此提高了併發效能。ConcurrentHashMap也增加了對常用複合操作的支援,比如"若沒有則新增":putIfAbsent(),替換:replace()。這2個操作都是原子操作。

  CopyOnWriteArrayList和CopyOnWriteArraySet分別代替List和Set,主要是在遍歷操作為主的情況下來代替同步的List和同步的Set,這也就是上面所述的思路:迭代過程要保證不出錯,除了加鎖,另外一種方法就是"克隆"容器物件。

  ConcurrentLinkedQuerue是一個先進先出的佇列。它是非阻塞佇列。

    ConcurrentSkipListMap可以在高效併發中替代SoredMap(例如用Collections.synchronzedMap包裝的TreeMap)。

  ConcurrentSkipListSet可以在高效併發中替代SoredSet(例如用Collections.synchronzedSet包裝的TreeMap)。

  本篇文章著重講解2個併發容器:ConcurrentHashMap和CopyOnWriteArrayList其中的ConcurrentHashMap,CopyOnWriteArrayList在下一篇文章中講述。

  大家都知道HashMap是非執行緒安全的,Hashtable是執行緒安全的,但是由於Hashtable是採用synchronized進行同步,相當於所有執行緒進行讀寫時都去競爭一把鎖,導致效率非常低下。

  ConcurrentHashMap可以做到讀取資料不加鎖,並且其內部的結構可以讓其在進行寫操作的時候能夠將鎖的粒度保持地儘量地小,不用對整個ConcurrentHashMap加鎖。

ConcurrentHashMap的內部結構

  ConcurrentHashMap為了提高本身的併發能力,在內部採用了一個叫做Segment的結構,一個Segment其實就是一個類Hash Table的結構,Segment內部維護了一個連結串列陣列,我們用下面這一幅圖來看下ConcurrentHashMap的內部結構:
圖表1
  從上面的結構我們可以瞭解到,ConcurrentHashMap定位一個元素的過程需要進行兩次Hash操作,第一次Hash定位到Segment,第二次Hash定位到元素所在的連結串列的頭部,因此,這一種結構的帶來的副作用是Hash的過程要比普通的HashMap要長,但是帶來的好處是寫操作的時候可以只對元素所在的Segment進行加鎖即可,不會影響到其他的Segment,這樣,在最理想的情況下,ConcurrentHashMap可以最高同時支援Segment數量大小的寫操作(剛好這些寫操作都非常平均地分佈在所有的Segment上),所以,通過這一種結構,ConcurrentHashMap的併發能力可以大大的提高。

Segment

  我們再來具體瞭解一下Segment的資料結構:

1 2 3 4 5 6 7 static final class Segment<K,V> extends ReentrantLock implements Serializable { transient volatile int count; transient int modCount; transient int threshold; transient volatile HashEntry<K,V>[] table; final float loadFactor; }

  詳細解釋一下Segment裡面的成員變數的意義:

  • count:Segment中元素的數量
  • modCount:對table的大小造成影響的操作的數量(比如put或者remove操作)
  • threshold:閾值,Segment裡面元素的數量超過這個值依舊就會對Segment進行擴容
  • table:連結串列陣列,陣列中的每一個元素代表了一個連結串列的頭部
  • loadFactor:負載因子,用於確定threshold

HashEntry

  Segment中的元素是以HashEntry的形式存放在連結串列陣列中的,看一下HashEntry的結構:

1 2 3 4 5 6 static final class HashEntry<K,V> { final K key; final int hash; volatile V value; final HashEntry<K,V> next; }

  可以看到HashEntry的一個特點,除了value以外,其他的幾個變數都是final的,這樣做是為了防止連結串列結構被破壞,出現ConcurrentModification的情況。

ConcurrentHashMap的初始化

  下面我們來結合原始碼來具體分析一下ConcurrentHashMap的實現,先看下初始化方法:

1 2 3 4 5 6 7 8 9 10 11 12 13 14

相關推薦

【轉】Java併發程式設計併發容器ConcurrentHashMap

  JDK5中添加了新的concurrent包,相對同步容器而言,併發容器通過一些機制改進了併發效能。因為同步容器將所有對容器狀態的訪問都序列化了,這樣保證了執行緒的安全性,所以這種方法的代價就是嚴重降低了併發性,當多個執行緒競爭容器時,吞吐量嚴重降低。因此Java5.0開始針對多執行緒併發訪問設計,提供了併

10-Java併發程式設計併發容器ConcurrentHashMap(轉載)

Java併發程式設計:併發容器之ConcurrentHashMap(轉載)   下面這部分內容轉載自:   JDK5中添加了新的concurrent包,相對同步容器而言,併發容器通過一些機制改進了併發效能。因為同步容器將所有對容器狀態的訪問都 序列化了,這樣保證了執

Java併發程式設計併發容器ConcurrentHashMap

下面這部分內容轉載自:   JDK5中添加了新的concurrent包,相對同步容器而言,併發容器通過一些機制改進了併發效能。因為同步容器將所有對容器狀態的訪問都 序列化了,這樣保證了執行緒的安全性,所以這種方法的代價就是嚴重降低了併發性,當多個執行緒

【34】Java併發程式設計併發容器CopyOnWriteArrayList(轉載)

Java併發程式設計:併發容器之CopyOnWriteArrayList(轉載)   原文連結:   http://ifeve.com/java-copy-on-write/      Copy-On-Write簡稱COW,是一種用於程式設計中的優化策略。其基本思路是,從一開始大家都

11-Java併發程式設計併發容器CopyOnWriteArrayList(轉載)

Java併發程式設計:併發容器之CopyOnWriteArrayList(轉載)   原文連結:   Copy-On-Write簡稱COW,是一種用於程式設計中的優化策略。其基本思路是,從一開始大家都在共享同一個內容,當某個人想要修改這個內容的時候,才會真正把內容

Java併發程式設計併發容器CopyOnWriteArrayList(轉載)

  原文連結:   Copy-On-Write簡稱COW,是一種用於程式設計中的優化策略。其基本思路是,從一開始大家都在共享同一個內容,當某個人想要修改這個內容的時候,才會真正把內容Copy出去形成一個新的內容然後再改,這是一種延時懶惰策略。從JDK1.5開始J

Java併發程式設計併發容器CopyOnWriteArrayList

原文連結:   Copy-On-Write簡稱COW,是一種用於程式設計中的優化策略。其基本思路是,從一開始大家都在共享同一個內容,當某個人想要修改這個內容的時候,才會真正把內容Copy出去形成一個新的內容然後再改,這是一種延時懶惰策略。從JDK1.5開

【轉】Java併發程式設計同步容器

  為了方便編寫出執行緒安全的程式,Java裡面提供了一些執行緒安全類和併發工具,比如:同步容器、併發容器、阻塞佇列、Synchronizer(比如CountDownLatch)。今天我們就來討論下同步容器。   一、為什麼會出現同步容器?   在Java的集合容器框架中,主要有四大類別:Li

(2.1.27.1)Java併發程式設計併發

在物理計算機中CPU為了提高處理速度,添加了快取記憶體與CPU亂序執行 一、 併發的起源 為了提高計算機處理資料的速度,現代的計算機都支援多工處理。 在32位windows作業系統中 ,多工處理是指系統可同時執行多個程序,而每個程序也可同時執行多個執行

Java並發--並發容器ConcurrentHashMap

替代 性能 新的 targe net 出現 float 分別是 unlock   下面這部分內容轉載自:   http://www.haogongju.net/art/2350374   JDK5中添加了新的concurrent包,相對同步容器而言,並發容器通過一些機制改進

併發程式設計併發Queue介面

佇列是一種先進先出或者後進後出的資料結構。在此我們模擬一下佇列這種資料結構: MyQueue.java定義如下: public class MyQueue { //佇列的容器 private LinkedList<Object> list = new L

【搞定Java併發程式設計】第21篇Java併發容器ConcurrentHashMap詳解

上一篇:讀寫鎖 --- ReentrantReadWriteLock詳解 本文目錄: 1、為什麼要使用ConcurrentHashMap? 2、ConcurrentHashMap的實現 2.1、ConcurrentHashMap中主要的成員變數、成員方法和內部類 2.2、分段鎖的

(2.1.27.16)Java併發程式設計LockConcurrentHashMap

ConcurrentHashMap 和 HashMap 的底層實現都是 陣列+連結串列或紅黑樹 構成的。 HashMap 的原始碼分析見:Java集合框架——HashMap原始碼分析 ConcurrentHashMap 相比 HashMap 支援多執行緒下的操

Java併發(十八)阻塞佇列BlockingQueue BlockingQueue(阻塞佇列)詳解 二叉堆(一) 圖文解析 和 C語言的實現 多執行緒程式設計:阻塞、併發佇列的使用總結 Java併發程式設計:阻塞佇列 java阻塞佇列 BlockingQueue(阻塞佇列)詳解

阻塞佇列(BlockingQueue)是一個支援兩個附加操作的佇列。 這兩個附加的操作是:在佇列為空時,獲取元素的執行緒會等待佇列變為非空。當佇列滿時,儲存元素的執行緒會等待佇列可用。 阻塞佇列常用於生產者和消費者的場景,生產者是往佇列裡新增元素的執行緒,消費者是從佇列裡拿元素的執行緒。阻塞佇列就是生產者

(2.1.27.11)Java併發程式設計LockReentrantReadWriteLock 讀寫分離獨享式重入鎖

我們在介紹AbstractQueuedSynchronizer的時候介紹過,AQS支援獨佔式同步狀態獲取/釋放、共享式同步狀態獲取/釋放兩種模式,對應的典型應用分別是ReentrantLock和Semaphore AQS還可以混合兩種模式使用,讀寫鎖Reent

(2.1.27.13)Java併發程式設計LockCountDownLatch計數式獨享鎖

CountDownLatch是一種java.util.concurrent包下一個同步工具類,它允許一個或多個執行緒等待直到在其他執行緒中一組操作執行完成。 相對於前文的鎖,它主要實現了: 呼叫指定次release後,才會釋放鎖 一、使用 public st

Java併發程式設計Copy-On-Write容器

Copy-On-Write簡稱COW,是一種用於程式設計中的優化策略。其基本思路是,從一開始大家都在共享同一個內容,當某個人想要修改這個內容的時候,才會真正把內容Copy出去形成一個新的內容然後再改,這是一種延時懶惰策略。從JDK1.5開始Java併發包裡提供了兩個使用CopyOnWrite

Java併發程式設計volatile關鍵字解析

volatile這個關鍵字可能很多朋友都聽說過,或許也都用過。在Java 5之前,它是一個備受爭議的關鍵字,因為在程式中使用它往往會導致出人意料的結果。在Java 5之後,volatile關鍵字才得以重獲生機。   volatile關鍵字雖然從字面上理解起來比較簡單,但是要

java併發程式設計守護執行緒(Daemon)

在Java中有兩類執行緒:User Thread(使用者執行緒)、Daemon Thread(守護執行緒) 用個比較通俗的比喻,任何一個守護執行緒都是整個JVM中所有非守護執行緒的保姆:只要當前JVM例項中尚存在任何一個非守護執行緒沒有結束,守護執行緒就全部工作;只有當最後一

Java concurrent Framework併發容器ConcurrentHashMap(JDK5,6,7,8)原始碼分析&ConcurrentSkipListMap

ConcurrentHashMap ConcurrentHashMap是一個執行緒安全的Hash Table,它的主要功能是提供了一組和HashTable功能相同但是執行緒安全的方法。ConcurrentHashMap可以做到讀取資料不加鎖,並且其內部的結構可以讓其在進行寫