Bootstrap

一文讲解HashMap线程安全相关问题(上)

  • 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。

;