hashMap是否線程安全基本上是在每次面試都會問的了,而99%的JAVA程序員都知道hashMap是非線程安全的,不過知道其底層原因的應該不多,下面來說下為什么是線程不安全的!
我們都知道,hashMap是一種在開發中最常用的數據結構(key-value型),因為它很快(O(1)常數級別的查詢),在存儲的時候通過計算key的hash值,將value存在對應的桶里(數組的一個元素),然后通過
這個過程是線程安全的,因為就算是發生了線程同享資源,無非就是插入的數據順序問題而已,無傷大雅,但是我們都知道,hashMap為了防止數據查詢過慢(如果單鏈表中的數據過大,相當于
hashMap怎么實現擴容呢?一旦需要擴容的時候,會新建一個兩倍容量的hashMap,并把原來的元素重新做hash存入新的hash數組,底層源碼使用的resize方法:
在resize方法中需要調用
當thread1執行到Entry<k,v>next=e.next的時候,把原來的key7指向key3,變為了key3指向key7,因為java是搶占式線程,此時thread2開始執行,不過在線程2中的快照中,還是key7指向key3(但實質key3已經指向了key7)!
經過線程2的處理完成,線程繼續處理,這個時候key3指向key7,反過來key7也指向key3,這時候
等到查詢方法查找到這個hash數組的時候,查詢出現了
所以hashMap是非線程安全的,相對應的hashTable擁有著和hashMap類似的結構,但是因為hashTable中的所有方法都加了鎖(synchonize),所以在多線程處理中,應該是用hashTable來換取數據的安全性!