HashMap在1 7 1 8中的執行緒安全問題

2022-06-04 07:09:09 字數 1740 閱讀 1160

在jdk1.7中,當併發執行擴容操作時會造成環形鏈和資料丟失的情況。

資料丟失:

在jdk1.8中,在併發執行put操作時會發生資料覆蓋的情況。

1、執行緒安全

兩者最主要的區別在於hashtable是執行緒安全,而hashmap則非執行緒安全。

hashtable的實現方法裡面都新增了synchronized關鍵字來確保執行緒同步,因此相對而言hashmap效能會高一些,我們平時使用時若無特殊需求建議使用hashmap,在多執行緒環境下若使用hashmap需要使用collections.synchronizedmap()方法來獲取乙個執行緒安全的集合。

note:collections.synchronizedmap()實現原理是collections定義了乙個synchronizedmap的內部類,這個類實現了map介面,在呼叫方法時使用synchronized來保證執行緒同步,當然了實際上操作的還是我們傳入的hashmap例項,簡單的說就是collections.synchronizedmap()方法幫我們在操作hashmap時自動新增了synchronized來實現執行緒同步,類似的其它collections.synchronizedxx方法也是類似原理。

2、針對null的不同

hashmap可以使用null作為key,而hashtable則不允許null作為key

雖說hashmap支援null值作為key,不過建議還是盡量避免這樣使用,因為一旦不小心使用了,若因此引發一些問題,排查起來很是費事。

note:hashmap以null作為key時,總是儲存在table陣列的第乙個節點上。

3、繼承結構

hashmap是對map介面的實現,hashtable實現了map介面和dictionary抽象類。

4、初始容量與擴容

hashmap的初始容量為16,hashtable初始容量為11,兩者的填充因子預設都是0.75。

hashmap擴容時是當前容量翻倍即:capacity2,hashtable擴容時是容量翻倍+1即:capacity2+1。

5、兩者計算hash的方法不同

hashtable計算hash是直接使用key的hashcode對table陣列的長度直接進行取模

int hash = key.hashcode();

int index = (hash & 0x7fffffff) % tab.length;

因為hashtable,concurrenthashmap它們是用於多執行緒的,併發的 ,如果map.get(key)得到了null,不能判斷到底是對映的value是null,還是因為沒有找到對應的key而為空

翻譯一下最後一句話,其實contains(key)也是可以使用synchronized進行同步的,所以呼叫contains(key)得到的就是該執行緒本時刻map的狀態,本身不存在歧義。問題的關鍵在於多執行緒情況下,即便此刻你通過contains(key)知曉了是否包含null,下一步當你使用這個結果去做一些事情時可能其他執行緒已經改變了這種狀態,這在單執行緒下是不可能發生的。

這是因為hashtable使用的是安全失敗機制(fail-safe),這種機制會使你此次讀到的資料不一定是最新的資料。

如果你使用null值,就會使得其無法判斷對應的key是不存在還是為空,因為你無法再呼叫一次contain(key)來對key是否存在進行判斷(意思是contains不可靠,看上面那一段),concurrenthashmap同理。

HashMap在java併發中如何發生死迴圈

在多執行緒環境中,使用hashmap進行put操作時會引起死迴圈,導致cpu使用接近100 下面通過 分析一下為什麼會發生死迴圈。static class entryimplements map.entry the table,resized as necessary.length must alw...

蛇形走線在PCB設計中的作用

pcb上的任何一條走線在通過高頻訊號的情況下都會對該訊號造成時延時,蛇形走線的主要作用是補償 同一組相關 訊號線中延時較小的部分,這些部分通常是沒有或比其它訊號少通過另外的邏輯處理 最典型的就是時鐘線,通常它不需經過任何其它邏輯處理,因而其延 時會小於其它相關訊號。高速數字pcb板的等線長是為了使各...

java中hashmap的作用

就是乙個鍵值對應的集合 hashmap a new hashmap a.put name abcdef key是name,value是字串abcdef system.out.println a.get name 根據key取得其值並輸出 list list new arraylist list.ad...