卡码笔记
首页
计算机基础
C++
Java
面经
笔记广场 (opens new window)
代码随想录 (opens new window)
首页
计算机基础
C++
Java
面经
笔记广场 (opens new window)
代码随想录 (opens new window)
  • 基础与面向对象

  • 集合

    • Java常见集合类有哪些?
    • Map接口有哪些实现类?
    • ArrayList和LinkedList的区别?
    • ArrayList和普通数组的区别是什么?
    • ArrayList扩容机制是什么?
    • HashMap、HashSet、HashTable和ConcurrentHashMap的区别?
    • Java中HashMap的底层实现是什么?
    • HashMap的put方法的流程是怎样的?
    • HashMap的扩容机制?
    • HashMap为什么是线程不安全的?如何实现线程安全?
      • 简要回答
      • 详细回答
      • 知识图解
      • 知识扩展
    • Hash冲突的解决方案有哪些?HashMap是怎样解决Hash冲突的?
    • concurrentHashMap如何保证线程安全?
    • 哪些集合类是线程安全的,哪些是线程不安全的?
  • 异常

  • 字符串

  • JVM

  • 并发与多线程

  • JDK

  • Spring

  • 设计模式

# HashMap线程安全

# 简要回答

  1. HashMap为什么是线程不安全的?
    • HashMap的操作不是原子的,多个线程操作一个HashMap对象时,可能会导致数据不一致,并发修改异常。
  2. 如何实现线程安全?
    • 使用Collections.synchronizedMap() 方法,返回一个线程安全的Map对象。
    • 使用ConcurrentHashMap类,它是线程安全的。
    • 使用锁机制,在HashMap的操作中加显式锁。

# 详细回答

  1. HashMap存在的问题
    • JDK1.7 采用数组+链表的数据结构,在多线程背景下,数组扩容时可能会导致Entry链死循环。
    • HashMap并发执行put()操作时会出现数据覆盖问题,因为put()方法没有加锁,多线程环境可能会出现数据覆盖问题。
    • HashMap的迭代器是快速失败迭代器,并发修改会破坏迭代器的遍历逻辑,导致数据不一致。
  2. 实现HashMap线程安全的方法
  • 使用Collections.synchronizedMap()方法,通过该方法创建一个线程安全的HashMap对象,返回一个同步的Map包装器,使所有对Map的操作都同步执行。
Map<String,String> synchronizedMap = Collections.synchronizedMap(new HashMap<>());
1
  • 使用ConcurrentHashMap类,它专门设计用于多线程环境的哈希表实现。它使用分段锁机制,允许多个线程同时进行读操作,提高并发性能。
Map<String,String> concurrentHashMap = new ConcurrentHashMap<>();
1
  • 使用锁机制,在HashMap的操作中加显式锁(如ReentrantLock)来保证线程安全。
Map<String,String> map = new HashMap<>();
ReentrantLock lock = new ReentrantLock();

// 在需要线程安全的操作中使用锁
lock.lock();
try {
    // 进行线程安全的操作
} finally {
    lock.unlock();
}
1
2
3
4
5
6
7
8
9
10

# 知识图解

  1. HashMap死循环形成图解 image

# 知识扩展

  1. 扩展
    • 并发编程的3个核心特性:原子性、可见性、有序性。
    • 迭代器设计模式:
      • 快速失败:迭代器实时检查modCount,一旦发现并发修改就抛出异常,实现强一致性,牺牲并发性能。
      • 弱一致性:允许并发修改,迭代器可能不是最新的,支持高并发。
  2. 面试官可能追问:
  • Q1:你能从并发编程的角度解释一下HashMap为什么是线程不安全的吗?
    1. 原子性:HashMap的put()方法不是原子操作,并发时会被中断,导致数据覆盖。
    2. 可见性:HashMap的modCount数组元素等共享变量未使用volatile修饰,线程A修改后,线程B可能看到旧值,导致迭代器判断错误。
    3. 有序性:HashMap红黑树的插入/删除有复杂的指针操作,并发时指令重排序可能会破坏树结构。
  • Q2:如果需要“强一致性”的线程安全Map,应该使用什么?
    1. 选Collections.synchronizedMap()方法。
    2. 在ConcurrentHashMap的迭代前后手动加锁。
  • Q3:"读多写少"的场景下,适合使用哪种线程安全的容器存储键值对?
    • 适合使用ConcurrentHashMap,其读操作无锁,写操作加桶级锁,“读多写少”的场景下,ConcurrentHashMap几乎无竞争,性能好。
  • Q4:为什么ConcurrentHashMap不支持键为null?但是HashMap支持?
    • 在单线程场景下,null的hash值为0可以正常存储,但ConcurrentHashMap是并发容器,若允许null,调用get()方法时返回null,无法区分键不存在还是键存在但是值为null,导致并发场景下的逻辑错误。
Last Updated: 3/10/2026, 6:08:48 PM

← HashMap的扩容机制? Hash冲突的解决方案有哪些?HashMap是怎样解决Hash冲突的? →

评论

验证登录状态...

侧边栏
夜间
卡码简历
代码随想录
卡码投递表🔥
2026群
添加客服微信 PS:通过微信后,请发送姓名-学校-年级-2026实习/校招
支持卡码笔记
鼓励/支持/赞赏Carl
1. 如果感觉本站对你很有帮助,也可以请Carl喝杯奶茶,金额大小不重要,心意已经收下
2. 希望大家都能梦想成真,有好的前程,加油💪