併發容器的原理,七大併發容器詳解、及使用場景
併發容器的由來
在Java併發程式設計中,經常聽到Java集合類,同步容器、併發容器,那麼他們有哪些具體分類,以及各自之間的區別和優劣呢?
只有把這些梳理清楚了,你才能真正掌握在高併發的環境下,正確使用好併發容器,我們先從Java集合類,同步容器談起。
1.什麼是同步容器
Java的集合容器框架中,主要有四大類別:List、Set、Queue、Map,大家熟知的這些集合類ArrayList、LinkedList、HashMap這些容器都是非執行緒安全的。
如果有多個執行緒併發地訪問這些容器時,就會出現問題。因此,在編寫程式時,在多執行緒環境下必須要求程式設計師手動地在任何訪問到這些容器的地方進行同步處理,這樣導致在使用這些容器的時候非常地不方便。
所以,Java先提供了同步容器供使用者使用。
同步容器可以簡單地理解為透過synchronized來實現同步的容器,比如Vector、Hashtable以及SynchronizedList等容器。
2.同步容器,主要的分類:
- Vector
- Stack
- HashTable
- Collections.synchronized方法生成
同步容器面臨的問題
可以透過檢視Vector,Hashtable等這些同步容器的實現程式碼,可以看到這些容器實現執行緒安全的方式就是將它們的狀態封裝起來,並在需要同步的方法上加上關鍵字synchronized。
這樣做的代價是削弱了併發性,當多個執行緒共同競爭容器級的鎖時,吞吐量就會降低。
例如: HashTable只要有一條執行緒獲取了容器的鎖之後,其他所有的執行緒訪問同步函式都會被阻塞,因此同一時刻只能有一條執行緒訪問同步函式。
因此為了解決同步容器的效能問題,所以才有了併發容器。
什麼是併發容器
java.util.concurrent包中提供了多種併發類容器。
併發類容器是專門針對多執行緒併發設計的,使用了鎖分段技術,只對操作的位置進行同步操作,但是其他沒有操作的位置其他執行緒仍然可以訪問,提高了程式的吞吐量。
採用了CAS演算法和部分程式碼使用synchronized鎖保證執行緒安全。
併發容器有哪些分類
1.ConcurrentHashMap
對應的非併發容器:HashMap
目標:代替Hashtable、synchronizedMap,支援複合操作
原理:JDK6中採用一種更加細粒度的加鎖機制Segment“分段鎖”,JDK8中採用CAS無鎖演算法。
2.CopyOnWriteArrayList
對應的非併發容器:ArrayList
目標:代替Vector、synchronizedList
原理:利用高併發往往是讀多寫少的特性,對讀操作不加鎖,對寫操作,先複製一份新的集合,在新的集合上面修改,然後將新集合賦值給舊的引用,並透過volatile 保證其可見性,當然寫操作的鎖是必不可少的了。
3.CopyOnWriteArraySet
對應的非併發容器:HashSet
目標:代替synchronizedSet
原理:基於CopyOnWriteArrayList實現,其唯一的不同是在add時呼叫的是CopyOnWriteArrayList的addIfAbsent方法,其遍歷當前Object陣列,如Object陣列中已有了當前元素,則直接返回,如果沒有則放入Object陣列的尾部,並返回。
4.ConcurrentSkipListMap
對應的非併發容器:TreeMap
目標:代替synchronizedSortedMap(TreeMap)
原理:Skip list(跳錶)是一種可以代替平衡樹的資料結構,預設是按照Key值升序的。
5.ConcurrentSkipListSet
對應的非併發容器:TreeSet
目標:代替synchronizedSortedSet
原理:內部基於ConcurrentSkipListMap實現
6.ConcurrentLinkedQueue
不會阻塞的佇列
對應的非併發容器:Queue
原理:基於連結串列實現的FIFO佇列(LinkedList的併發版本)
7.LinkedBlockingQueue、ArrayBlockingQueue、PriorityBlockingQueue
對應的非併發容器:BlockingQueue
特點:擴充了Queue,增加了可阻塞的插入和獲取等操作
原理:透過ReentrantLock實現執行緒安全,透過Condition實現阻塞和喚醒
實現類:
- LinkedBlockingQueue:基於連結串列實現的可阻塞的FIFO佇列
- ArrayBlockingQueue:基於陣列實現的可阻塞的FIFO佇列
- PriorityBlockingQueue:按優先順序排序的佇列
ConcurrentHashMap的實現
HashMap,Hashtable與ConcurrentHashMap都是實現的雜湊表資料結構,在隨機讀取的時候效率很高。
Hashtable實現同步是利用synchronized關鍵字進行鎖定的,其是針對整張雜湊表進行鎖定的,即每次鎖住整張表讓執行緒獨佔,線上程安全的背後是巨大的浪費。
ConcurrentHashMap和Hashtable主要區別就是圍繞著鎖的粒度進行區別以及如何區鎖定。
上圖中,左邊是Hashtable的實現方式,可以看到鎖住整個雜湊表;而右邊則是ConcurrentHashMap的實現方式,單獨鎖住每一個桶(segment).ConcurrentHashMap將雜湊表分為16個桶(預設值),諸如get(),put(),remove()等常用操作只鎖當前需要用到的桶,而size()才鎖定整張表。
原來只能一個執行緒進入,現在卻能同時接受16個寫執行緒併發進入(寫執行緒需要鎖定,而讀執行緒幾乎不受限制)。
所以,才有了併發性的極大提升。
高併發程式設計,除了併發容器,還會涉及到併發工具類:CountDownLatch等,後續將詳細的介紹併發工具類,以及ConcurrentHashMap的底層實現細節,不僅要知其然,還要知其所以然,這樣才能更好的掌握好高併發程式設計。
本文由部落格一文多發平臺 釋出!
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/151/viewspace-2824489/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 詳解Java 容器(第⑤篇)——容器原始碼分析 - 併發容器Java原始碼
- 併發容器與框架——併發容器(二)框架
- 併發容器之ArrayBlockingQueue和LinkedBlockingQueue實現原理詳解BloC
- 詳解Java 容器(完結篇)——詳解容器的設計模式、List、Map、併發容器Java設計模式
- Java併發程式設計-鎖及併發容器Java程式設計
- Java併發(9)- 從同步容器到併發容器Java
- Java併發容器Java
- Java同步容器和併發容器Java
- 併發容器之ThreadLocalthread
- 併發容器之CopyOnWriteArrayList
- Java併發容器,底層原理深入分析Java
- 併發程式設計(二)——併發類容器ConcurrentMap程式設計
- 併發容器、框架、工具類框架
- Java併發指南14:Java併發容器ConcurrentSkipListMap與CopyOnWriteArrayListJava
- 《java併發程式設計的藝術》併發容器和框架Java程式設計框架
- Java併發佇列與容器Java佇列
- MySQL 在併發場景下的問題及解決思路MySql
- 併發-7-同步容器和ConcurrentHashMapHashMap
- 併發程式設計 — CAS 原理詳解程式設計
- HarmonyOS線性容器特性及使用場景
- PHP 併發場景的幾種解決方案PHP
- 通俗易懂,JDK 併發容器總結JDK
- 併發程式設計(一)——同步類容器程式設計
- 併發容器之ConcurrentHashMap(JDK 1.8版本)HashMapJDK
- 併發容器J.U.C -- AQS元件(一)AQS元件
- Nginx實現高速併發處理的原理詳解Nginx
- Java併發(十九)----Monitor原理及Synchronized原理Javasynchronized
- 併發容器J.U.C -- AQS同步元件(二)AQS元件
- 【詳解】併發程式的等待方式
- Java中的併發集合詳解Java
- 最強幹貨:Java併發之AQS原理詳解JavaAQS
- 併發程式設計ConcurrentLinkedQueue使用示例詳解程式設計
- [分散式][高併發]訊息佇列的使用場景、概念、常見問題及解決方案分散式佇列
- Go併發原理Go
- 請求合併與拆分在併發場景中應用
- Go 併發控制:errgroup 詳解Go
- Java併發之AQS詳解JavaAQS
- Java併發之CompletionService詳解Java