hashMap在多線程環境下的表現
- 在jdk1.7中多線程put時可能會導致get無限循環,具體表現為CPU使用率100%;
該方法實現的機制就是將每個鏈表轉化到新鏈表,並且鏈表中的位置發生反轉,而這在多線程情況下是很容易造成鏈表迴路,從而發生 get() 死循環。所以只要保證建新鏈時還是按照原來的順序的話就不會產生循環(JDK 8 的改進)。即在jdk1.7是採用的頭插法,在jdk1.8使用了尾插法解決。
HashMap死循環只發生在JDK1.7版本中,主要原因是JDK1.7中的HashMap,在頭插法 加 鏈表 加 多線程併發 加 擴容這幾個情形累加到一起就會形成死循環。多線程環境下建議採用ConcurrentHashMap替代。
- 多線程put時可能導致元素丟失 原因:當多個線程同時執行addEntry(hash,key ,value,i)時,如果產生哈希碰撞,導致兩個線程得到同樣的bucketIndex去存儲,就可能會發生元素覆蓋丟失的情況
Hashmap中的鏈表大小超過八個時會自動轉化為紅黑樹,當刪除小於六時重新變為鏈表,為啥呢?
根據泊松分佈,在負載因子默認為0.75的時候,單個hash槽內元素個數為8的概率小於百萬分之一,所以將7作為一個分水嶺,等於7的時候不轉換,大於等於8的時候才進行轉換,小於等於6的時候就化為鏈表。 避免樹和鏈表的頻繁轉換
從時間複雜度分析,樹的查詢時間複雜度是logn,所於大於等於8使用紅黑樹。
Collections.synchronizedMap是怎麼實現線程安全的
在SynchronizedMap內部維護了一個普通對象Map,還有排斥鎖mutex,如圖
我們在調用這個方法的時候就需要傳入一個Map,可以看到有兩個構造器,如果你傳入了mutex參數,則將對象排斥鎖賦值為傳入的對象。
如果沒有,則將對象排斥鎖賦值為this,即調用synchronizedMap的對象,就是上面的Map。
創建出synchronizedMap之後,再操作map的時候,就會對方法上鎖。