本文的分析是基於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...