日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

concurrenthashmap是什么锁_多线程为什么要用ConcurrentHashMap

發布時間:2025/3/20 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 concurrenthashmap是什么锁_多线程为什么要用ConcurrentHashMap 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

今天我們要說的是關于集合的問題,實際上跟鎖也有一定的關系,讓我們來一起看看吧。

一、簡介

1、是什么

ConcurrentHashMap是Java5中新增加的一個線程安全的Map集合,可以用來替代HashTable。對于ConcurrentHashMap是如何提高其效率的,可能大多人只是知道它使用了多個鎖代替HashTable中的單個鎖,也就是鎖分離技術(Lock Stripping)。

2、為什么

為什么不用HashMap

hashmap本質數據加鏈表。根據key取得hash值,然后計算出數組下標,如果多個key對應到同一個下標,就用鏈表串起來,新插入的在前面。而且hashmap在單線程情況下效率較高。

但是在多線程環境下,使用Hashmap進行put操作會引起死循環,導致CPU利用率接近100%,所以在并發情況下不能使用HashMap。

為什么不用HashTable

HashTable容器使用synchronized來保證線程安全,但在線程競爭激烈的情況下HashTable的效率非常低下。因為當一個線程訪問HashTable的同步方法時,其他線程訪問HashTable的同步方法時,可能會進入阻塞或輪詢狀態。如線程1使用put進行添加元素,線程2不但不能使用put方法添加元素,并且也不能使用get方法來獲取元素,所以競爭越激烈效率越低。

為什么要用ConcurrentHashMap

HashTable容器在競爭激烈的并發環境下表現出效率低下的原因,是因為所有訪問HashTable的線程都必須競爭同一把鎖,那假如容器里有多把鎖,每一把鎖用于鎖容器其中一部分數據,那么當多線程訪問容器里不同數據段的數據時,線程間就不會存在鎖競爭,從而可以有效的提高并發訪問效率,這就是ConcurrentHashMap所使用的鎖分段技術,首先將數據分成一段一段的存儲,然后給每一段數據配一把鎖,當一個線程占用鎖訪問其中一個段數據的時候,其他段的數據也能被其他線程訪問。

二、深入解析

1、結構圖解析

ConcurrentHashMap和Hashtable主要區別就是圍繞著鎖的粒度以及如何鎖,可以簡單理解成把一個大的HashTable分解成多個,形成了鎖分離。而Hashtable的實現方式是—鎖整個hash表

從圖中可以看到,ConcurrentHashMap內部分為很多個Segment,每一個Segment擁有一把鎖,然后每個Segment(繼承ReentrantLock)下面包含很多個HashEntry列表數組。對于一個key,需要經過三次(為什么要hash三次下文會詳細講解)hash操作,才能最終定位這個元素的位置,這三次hash分別為:

對于一個key,先進行一次hash操作,得到hash值h1,也即h1 = hash1(key);

將得到的h1的高幾位進行第二次hash,得到hash值h2,也即h2 = hash2(h1高幾位),通過h2能夠確定該元素的放在哪個Segment;

將得到的h1進行第三次hash,得到hash值h3,也即h3 = hash3(h1),通過h3能夠確定該元素放置在哪個HashEntry。

2、實現原理

ConcurrentHashMap把Map分成了N個Segment(默認16),其中Segment是線程同步的,相當于分成了N個Hashtable。當實現Put方法時,在key值經過正常的hash后,還要再經過一次segmentForHash算法,用來分配具體防盜哪個Segment。后來的線程如果經過計算也是放在這個Segment下,則需要先獲取鎖,如果計算得出應該放在其他的Segment,則正常執行,不會影響效率,以此實現線程安全。ConcurrentHashMap使用鎖分離技術,只要多個修改操作不發生在同一個Segment上,它們就可以并發進行。

有些方法需要跨段,比如size()和containsValue(),需要鎖定整個表而而不僅僅是某個段,這需要按順序鎖定所有段,操作完畢后,又按順序釋放所有段的鎖。這里“按順序”是很重要的,否則極有可能出現死鎖,在ConcurrentHashMap內部,段數組是final的,并且其成員變量實際上也是final的,但是,僅僅是將數組聲明為final的并不保證數組成員也是final的,這需要實現上的保證。這可以確保不會出現死鎖,因為獲得鎖的順序是固定的。

3、源碼詳解

這里不再細說,網上有很多。推薦Java并發包學習八]深度剖析ConcurrentHashMap

總結:

這個類其實在我們項目中的緩存使用到了,利用ConcurrentHashMap來存放一些常用的信息,由于是在并發的情況下使用,考慮到性能的問題,優先選用ConcurrentHashMap類。不過我建議大家還是要多看看源碼,從中會受益很多。

總結

以上是生活随笔為你收集整理的concurrenthashmap是什么锁_多线程为什么要用ConcurrentHashMap的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。