hashmap 线程不安全 的原因

HashMap 在多线程环境下线程不安全的原因有以下几个方面:

1. 扩容(Rehashing)时的竞争问题

        当 HashMap 中的元素数量达到一定程度时(默认是容量的 75%),它会进行扩容操作。扩容时,需要将原来桶(bucket)中的数据重新分布到新的桶中,这个过程称为 rehashing。多线程情况下,多个线程同时触发扩容操作,可能导致两个或多个线程对同一个桶进行操作,从而引发数据不一致问题,甚至导致死循环或丢失元素。

2. 多线程下的 put 操作

        在多线程环境下,如果多个线程同时对 HashMap 进行 put 操作,由于 HashMap 并没有同步机制,不同线程可能会同时操作同一个桶,覆盖掉其他线程正在写入的数据,导致数据丢失或冲突。

3. 链表和树结构的非原子操作

        HashMap 底层存储结构是数组 + 链表/红黑树。插入数据时,如果发生哈希碰撞,多个元素会被插入到同一个桶中,形成链表或红黑树。这些插入操作并非原子操作(即使是单个元素插入都涉及到多个步骤,比如查找对应的桶,插入数据等),在多线程环境下,两个线程可能同时修改链表结构,导致链表的断裂、数据丢失或死循环。

4. 死循环问题

        在 JDK 1.7 中,HashMap 使用的是链表结构,在多线程并发插入时,可能会在扩容(rehash)过程中形成环形链表。这会导致程序陷入死循环,尤其是在 get 操作中,造成 CPU 利用率飙升。

举例:

假设两个线程同时执行 put 操作:

  • 线程 A 在计算桶位置并插入数据时,线程 B 也计算了同一个桶的位置并插入数据。由于操作并未同步,可能导致其中一个线程的写入被覆盖。

5. 读写操作的非原子性

        多个线程同时对 HashMap 进行读写操作时,读操作和写操作不是原子的。如果一个线程正在执行 put 操作,而另一个线程执行 get,由于没有同步控制,可能会读取到未完整插入的数据,导致返回空值或错误数据。

总结:

        HashMap 的线程不安全主要原因在于没有对共享数据的访问进行同步控制,多线程环境下可能引发数据竞争、扩容时数据丢失、链表断裂或死循环等问题。如果需要在多线程环境下使用类似 HashMap 的数据结构,应该使用线程安全的实现,例如 ConcurrentHashMap

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值