tft每日頭條

 > 生活

 > concurrent hashmap底層原理1.8

concurrent hashmap底層原理1.8

生活 更新时间:2024-11-29 23:44:56
ConcurrentHashMap簡單介紹

相比HashMap而言,是多線程安全的,其底層數據與HashMap的數據結構相同。

JDK1.7之前

通過對多個數組分段鎖機制(Segment)來實現的加鎖,默認16個Segment,16個分段,每個Segment對應Node[]數組,每個Segment有一把鎖,也就是說對一個Segment裡的Node[]數組的不同的元素如果要put操作的話,其實都是要競争一個鎖,串行化來處理的。

這種情況下,如果某一時間,同時并發訪問同一個數組段,其最大并發度受段的個數限制,效率還是低。

JDK1.8後

實現原理摒棄了這種設計,做了鎖粒度的細化,一個大的數組,數組裡每個元素進行put操作,都是有一個不同的鎖,剛開始進行put的時候,如果當前位置為空,執行CAS操作設值。

如果兩個線程都是在數組[5]這個位置進行put,這個時候如果裡面的值不為null,對數組[5]這個位置進行put的時候,采取的是synchronized(f)加鎖,鎖住這個節點,隻讓一個線程來處理鍊表或紅黑樹。

final V putVal(K key, V value, boolean onlyIfAbsent) { if (key == null || value == null) throw new NullPointerException(); int hash = spread(key.hashCode()); int binCount = 0; for (Node<K,V>[] tab = table;;) { Node<K,V> f; int n, i, fh; if (tab == null || (n = tab.length) == 0) tab = initTable(); else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {//如果當前位置沒有值,就進入CAS操作,成功就結束 if (casTabAt(tab, i, null,new Node<K,V>(hash, key, value, null)))//多線程的時候不成功,進入下次for循環設值 break; // no lock when adding to empty bin } else if ((fh = f.hash) == MOVED) tab = helpTransfer(tab, f); else { V oldVal = null; synchronized (f) {//鎖住這個節點,隻讓一個線程來處理鍊表或紅黑樹 if (tabAt(tab, i) == f) { if (fh >= 0) { binCount = 1; for (Node<K,V> e = f;; binCount) { K ek; if (e.hash == hash && ((ek = e.key) == key || (ek != null && key.equals(ek)))) { oldVal = e.val; if (!onlyIfAbsent) e.val = value; break; } Node<K,V> pred = e; if ((e = e.next) == null) { pred.next = new Node<K,V>(hash, key, value, null); break; } } } else if (f instanceof TreeBin) { Node<K,V> p; binCount = 2; if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key, value)) != null) { oldVal = p.val; if (!onlyIfAbsent) p.val = value; } } } } if (binCount != 0) { if (binCount >= TREEIFY_THRESHOLD) treeifyBin(tab, i); if (oldVal != null) return oldVal; break; } } } addCount(1L, binCount); return null;

如何保證取值的安全?

如果是get(key)的時候,是基于Unsafe.getObjectVolatile(),volatile讀機制,來讀取數組裡的節點,而節點裡面的value也是加了volatile,盡可能給你保證說是讀到了其他線程修改的一個最新的值,但是不需要加鎖volatile V val;

Volatile底部實現原理,關注我,後面會講解。

ConcurrentHashMap和Hashtable的區别

主要體現在實現線程安全的方式上不同。

1、HashTable内部的方法基本都經過 synchronized 修飾。而synchronized關鍵字加鎖是對整個對象進行加鎖,也就是說在進行put等修改Hash表的操作時,鎖住了整個Hash表,從而使得其表現的效率低下。

concurrent hashmap底層原理1.8(底部鎖實現細節)1

2、ConcurrentHashMap主要從之前的分段加鎖機制優化到現在的鎖粒度的細化。

concurrent hashmap底層原理1.8(底部鎖實現細節)2

concurrent hashmap底層原理1.8(底部鎖實現細節)3

下篇開始講解List集合相關特性及原理。

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关生活资讯推荐

热门生活资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved