亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Java 中的線程安全容器

Seay / 3212人閱讀

摘要:一同步容器常用的一些容器例如都不是線程安全的,最簡單的將這些容器變?yōu)榫€程安全的方式,是給這些容器所有的方法都加上關鍵字。為了降低哈希沖突的成本,在鏈表長度超過時,將鏈表轉換為紅黑樹。

一、同步容器

常用的一些容器例如 ArrayList、HashMap、都不是線程安全的,最簡單的將這些容器變?yōu)榫€程安全的方式,是給這些容器所有的方法都加上 synchronized 關鍵字。

Java 的 Collections 中實現(xiàn)了這些同步容器:

簡單的使用如下:

List list = Collections.synchronizedList(new ArrayList<>());

Map map = Collections.synchronizedMap(new HashMap<>());

Set set = Collections.synchronizedSet(new HashSet<>());

同步容器雖然簡單,但是相應的效率較低,因為鎖的粒度較大。

循環(huán)遍歷同步容器

如果在遍歷同步容器的時候,組合了多個方法,這會可能會存在競態(tài)條件,仍然不是線程安全的。解決的辦法便是對容器加鎖。例如下面這樣:

public static void main(String[] args) {
    List list = Collections.synchronizedList(new ArrayList<>());
    
    //省略添加數(shù)據(jù)的操作
    
    String[] str = new String[list.size()];
    int k = 0;
    synchronized (list){
        Iterator iterator = list.iterator();
        while (iterator.hasNext()){
            str[k ++] = iterator.next();
        }
    }
}
二、并發(fā)容器

Java 中還提供了一系列并發(fā)容器,相比于同步容器,其性能更好。并發(fā)容器共分為了四類:List、Map、Set、Queue。

1. List

List 中一個最主要的實現(xiàn)類是 CopyOnWriteArrayList ,CopyOnWrite,即寫時復制,這樣的好處是讀操作是無鎖的。

其實現(xiàn)原理是內部維護了一個數(shù)組,內部變量 array 指向了這個數(shù)組。需要寫時,并不是在原數(shù)組上操作,而是將數(shù)組復制一份,在拷貝的數(shù)組中進行寫。完成后,將 array 指向新的數(shù)組。這樣一來,讀寫之間不互斥,效率得到了很大的提升。

需要注意的是 CopyOnWriteArrayList 適用于讀多寫少的場景,并且需要接受讀寫的暫時不一致,因為在寫的時候,并行的讀操作可能并不能馬上看到寫的結果。

2. Map

Map 的兩個主要實現(xiàn)類是 ConcurrentHashMapConcurrentSkipListMap,兩者主要的區(qū)別是:前者是無序的,后者是有序的。

2.1 ConcurrentHashMap

在 Java 1.7 中,ConcurrentHashMap 的實現(xiàn)使用的是分段鎖技術,其內部主要的數(shù)據(jù)結構是 Segment 和 HashEntry,ConcurrentHashMap 包含了一個 Segment 數(shù)組,每個 Segment 又包含一個 HashEntry 數(shù)組,每個 HashEntry 是一個存儲數(shù)據(jù)的鏈表結構。

其中 Segment 繼承了 ReentrantLock,每個 Segment 都有對應的鎖,需要修改數(shù)據(jù)的時候,需要獲取這把鎖。修改不同的 Segment 數(shù)據(jù),則完全可以并行,效率得到了提升。示意圖如下:

Java 1.8 又對 ConcurrentHashMap 做了較大的改進,放棄了分段鎖的技術。結構和 Java 1.8 中的 HashMap 類似,采用的是數(shù)組+鏈表/紅黑樹來實現(xiàn)。為了降低哈希沖突的成本,在鏈表長度超過 8 時,將鏈表轉換為紅黑樹。使用 CAS 和 synchronized 解決并發(fā)問題,鎖住鏈表或者紅黑樹的頭節(jié)點,只要沒有哈希沖突,則不會出現(xiàn)并發(fā)問題。示意圖如下:

2.2 ConcurrentSkipListMap

ConcurrentSkipListMap 保證有序的主要原因是,底層使用的是跳表這種數(shù)據(jù)結構,關于跳表的介紹,你可以查看數(shù)據(jù)結構中的內容。

3. Set

Set 的兩個實現(xiàn)是 CopyOnWriteArraySetConcurrentSkipListSet。

和前面說到的 CopyOnWriteArrayList 、ConcurrentSkipListMap 實現(xiàn)的原理類似。

4. Queue

隊列可以從兩方面進行分類:

單端和雙端:單端隊列指的是只能在隊首出隊,隊尾出隊,而雙端隊列指的是隊首和隊尾均可入隊和出隊。

阻塞和非阻塞:阻塞隊列指的是,當隊列滿的時候,入隊列阻塞;當隊列空的時候,出隊列阻塞。

Java 中,單端隊列使用 queue 標識,雙端隊列使用 deque 標識。

4.1 單端阻塞隊列

常用的實現(xiàn)類有:ArrayBlockingQueueLinkedBlockingQueue、PriorityQueue。

4.2 單端非阻塞隊列

其實現(xiàn)類是 ConcurrentLinkedQueue

4.3 雙端阻塞隊列

其實現(xiàn)類是 LinkedBlockingDeque

4.4 雙端非阻塞隊列

其實現(xiàn)類是 ConcurrentLinkedDeque

使用其實都非常地簡單,就是入隊出隊之類的操作,這里不再贅述了。

文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://www.ezyhdfw.cn/yun/74635.html

相關文章

  • Java并發(fā),volatile+不可變容器對象能保證線程安全么?!

    摘要:同樣,用類型的變量來保存這些值也不是線程安全的。僅保證可見性,無法保證線程安全性。并且返回的結果是對象,是局部變量,并未使對象逸出,所以這里也是線程安全的。 《Java并發(fā)編程實戰(zhàn)》第3章原文 《Java并發(fā)編程實戰(zhàn)》中3.4.2 示例:使用Volatile類型來發(fā)布不可變對象 在前面的UnsafeCachingFactorizer類中,我們嘗試用兩個AtomicReferences變...

    tyheist 評論0 收藏0
  • [Java并發(fā)-11] 并發(fā)容器的使用

    摘要:同步容器及其注意事項中的容器主要可以分為四個大類,分別是和,但并不是所有的容器都是線程安全的。并發(fā)容器及其注意事項在版本之前所謂的線程安全的容器,主要指的就是同步容器,當然因為所有方法都用來保證互斥,串行度太高了,性能太差了。 Java 并發(fā)包有很大一部分內容都是關于并發(fā)容器的,因此學習和搞懂這部分的內容很有必要。 Java 1.5 之前提供的同步容器雖然也能保證線程安全,但是性能很差...

    legendaryedu 評論0 收藏0
  • CopyOnWriteArrayList你都不知道,怎么拿offer?

    摘要:今天主要講解的是本文力求簡單講清每個知識點,希望大家看完能有所收獲一和回顧線程安全的和我們知道是用于替代的,是線程安全的容器。使用迭代器遍歷時不需要顯示加鎖,看看與方法的實現(xiàn)可能就有點眉目了。 前言 只有光頭才能變強 showImg(https://segmentfault.com/img/remote/1460000016931828?w=1120&h=640); 前一陣子寫過一篇C...

    noONE 評論0 收藏0
  • 想進大廠?50個多線程面試題,你會多少?(一)

    摘要:下面是線程相關的熱門面試題,你可以用它來好好準備面試。線程安全問題都是由全局變量及靜態(tài)變量引起的。持有自旋鎖的線程在之前應該釋放自旋鎖以便其它線程可以獲得自旋鎖。 最近看到網(wǎng)上流傳著,各種面試經(jīng)驗及面試題,往往都是一大堆技術題目貼上去,而沒有答案。 不管你是新程序員還是老手,你一定在面試中遇到過有關線程的問題。Java語言一個重要的特點就是內置了對并發(fā)的支持,讓Java大受企業(yè)和程序員...

    wow_worktile 評論0 收藏0
  • java線程安全支持有哪些?

    摘要:它能阻塞一組線程直到某個事件發(fā)生。與閉鎖的區(qū)別所有線程必須同時到達柵欄位置,才能繼續(xù)執(zhí)行。閉鎖用于等待事件,而柵欄用于等待其它線程。閉鎖一旦進入終止狀態(tài),就不能被重置,它是一次性對象,而柵欄可以重置。 同步容器。它的原理是將狀態(tài)封裝起來,并對每個公有方法都實行同步,使得每次只有1個線程能夠訪問容器的狀態(tài)。 Vector和HashTable Collections.synchroni...

    sewerganger 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<