併發資料結構----ConcurrentHashMap原理分析
阿新 • • 發佈:2019-02-02
該方法也是在持有段鎖(鎖定整個segment)的情況下執行的,這當然是為了併發的安全,修改資料是不能併發進行的,必須得有個判斷是否超限的語句以確保容量不足時能夠rehash。接著是找是否存在同樣一個key的結點,如果存在就直接替換這個結點的值。否則建立一個新的結點並新增到hash鏈的頭部,這時一定要修改modCount和count的值,同樣修改count的值一定要放在最後一步。put方法呼叫了rehash方法,reash方法實現得也很精巧,主要利用了table的大小為2^n,這裡就不介紹了。而比較難懂的是這句int index = hash & (tab.length - 1),原來segment裡面才是真正的hashtable,即每個segment是一個傳統意義上的hashtable,如上圖,從兩者的結構就可以看出區別,這裡就是找出需要的entry在table的哪一個位置,之後得到的entry就是這個鏈的第一個節點,如果e!=null,說明找到了,這是就要替換節點的值(onlyIfAbsent == false),否則,我們需要new一個entry,它的後繼是first,而讓tab[index]指向它,什麼意思呢?實際上就是將這個新entry插入到鏈頭,剩下的就非常容易理解了。V put(K key, int hash, V value, boolean onlyIfAbsent) { lock(); try { int c = count; if (c++ > threshold) // ensure capacity rehash(); HashEntry<K,V>[] tab = table; int index = hash & (tab.length - 1); HashEntry<K,V> first = tab[index]; HashEntry<K,V> e = first; while (e != null && (e.hash != hash || !key.equals(e.key))) e = e.next; V oldValue; if (e != null) { oldValue = e.value; if (!onlyIfAbsent) e.value = value; } else { oldValue = null; ++modCount; tab[index] = new HashEntry<K,V>(key, hash, first, value); count = c; // write-volatile } return oldValue; } finally { unlock(); } }