首先思考一下,为啥 HashMap 会存在线程安全性问题?
有的人脱口而出,JDK7 的 HashMap 因为采用头插法,多线程环境下会造成死循环,JDK8 虽然改用了尾插法,但多线程环境下仍然存在丢失更新的问题,所以 HashMap 存在线程安全性问题。
一听就是老八股人了,哈哈哈。
但其实上面的答案并不全面,而且很容易误导编程的新手,让新手总以为 HashMap 只是因为死循环或者丢失更新的问题才导致的线程不安全。
HashMap 之所以存在线程安全性问题,本质上是因为 HashMap 的"增删改"操作均是多步操作的集合,或者说是非原子的。
在多线程环境下,非原子的操作可能因为线程调度的问题,引发各种线程不安全性问题。以 put() 方法为例:
public V put(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
if (key == null)
return putForNullKey(value);
int hash = hash(key);
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Objec