HashMap實現原理(二) 多執行緒問題

2021-08-18 05:22:42 字數 1338 閱讀 6854

本文的分析是基於jdk1.7原始碼

前奏:我們都知道,hashmap的初始容量是16,當hashmap中的值的size超過threshold時,會進行擴容操作;擴容會執行resize—>transfer方法

hashmap之所以執行緒不安全就是因為在resize(transfer)的時候會不安全。

resize(transfer)會執行如下操作,並將原hash表中的內容移動到新的hash表中。

上**:

**解釋:

1. 對索引陣列中的元素遍歷

2. 對鍊錶上的每乙個節點遍歷:用next取得要轉移那個元素的下乙個,將e轉移到新hash表的頭部,使用頭插法插入節點

3. 迴圈2,直到鍊錶節點全部轉移

4. 迴圈1,知道所有索引陣列全部轉移

多執行緒舉例:

現有old table表,其中hash表的size=2,key=3,7,5. 假設hash演算法是key mod table.length; 則碰撞發生在table[1]。現在擴容將hash表resize到4,。

如圖:

現在有兩個執行緒 1和2。同時進行了put操作,並進入了transfer函式。並且執行緒1在如下處掛起。而執行緒2繼續執行完。

for (entry

e : table)

int i = indexfor(e.hash, newcapacity);

e.next = newtable[i];

newtable[i] = e;

e = next;}}

現在的狀態為:

執行緒2執行完後,執行緒1被喚醒。

執行e.next = newtable[i], 於是key(3)的next指向了執行緒1的新hash表,因為新hash表為空,所以e.next = null

執行newtable[i] = e,所以執行緒1的新hash表第乙個元素指向了執行緒2新hash表的key(3)

執行e = next,將e指向next, 所以新的e是key(7)

然後 1、現在的e結點是key(7),首先執行entry

多執行緒的實現原理(二)

synchronized 的實現原理和應用 synchronized有三種方式來加鎖 1.修飾例項方法,兩個執行緒同時訪問同乙個例項物件中的方法 synchronized this 時候會發生有乙個會被阻塞。public class demo extends thread catch interru...

多執行緒 ThreadLocal原理(二)

一 用法 threadlocal用於儲存某個執行緒共享變數 對於同乙個static threadlocal,不同執行緒只能從中get,set,remove自己的變數,而不會影響其他執行緒的變數。1 threadlocal.get 獲取threadlocal中當前執行緒共享變數的值。2 threadl...

多執行緒 Synchronize實現原理

前言 synchronize實現實現同步最常用的方式,但是它的底層實現呢?如何實現 通過synchronize修飾的 塊,執行緒訪問需要申請鎖才能訪問,但是當乙個物件的鎖已經被乙個執行緒拿到了,其他執行緒就拿不到這個物件的鎖,必須進入等待阻塞的狀態。monitor物件,在同步 塊的開始會引入moni...