- HashMap不是線程安全的,主要有以下幾個問題:
①、多線程下擴容會死循環。JDK1.7 中的 HashMap 使用的是頭插法插入元素,在多線程的環境下,擴容的時候就有可能導致出現環形鏈表,造成死循環。
JDK 8 時已經修復了這個問題,擴容時會保持鏈表原來的順序。
②、多線程的put可能會導致元素的丟失,因為計算出來的位置可能會被其他線程的put覆蓋。本來哈希沖突應該用鏈表的,但多線程時由于沒有加鎖,相同位置的元素可能就被干掉了;
③、put和get并發時,可能導致get為null。線程1執行put時,因為元素個數超出閾值而導致出現擴容,線程2此時執行get,就有可能出現這個問題;
- 因為線程1執行完table = newTab之后,線程2中的table此時也發生了變化,此時去get的時候當然會get到null了,因為元素還沒有轉移;
接下來說下map的同步和非同步問題
-
Hashtable 是 Map 接口的一個早期的同步實現,它的所有方法都是同步的,即每個方法都用 synchronized 關鍵字修飾,以確保線程安全。
隨著 JDK 版本的升級,Java 提供了更好的線程安全 Map 實現,如 ConcurrentHashMap。
如果是在單線程環境下,可以使用 HashMap。