面试题: ConcurrentHashMap 和 Hashtable 的区别是什么?

ConcurrentHashMap 和 Hashtable 都是 Java 中线程安全的哈希表实现,但它们在实现机制、性能以及使用场景方面存在显著差异。以下是它们的主要区别:

1. 实现方式和锁粒度

  • Hashtable
    • 使用了方法级别的同步(每个公开的方法都使用了 synchronized 关键字),这意味着在同一时间只能有一个线程可以操作 Hashtable 的任何方法。
    • 这种设计导致了一个严重的性能瓶颈,尤其是在读多写少的场景下,因为即使是读操作也需要获取锁。
  • ConcurrentHashMap
    • 在JDK 8之前,它通过分段锁(Segment)来减少锁的竞争,将整个哈希表划分为多个段,每个段都可以独立地进行并发访问。
    • 自JDK 8开始,ConcurrentHashMap 放弃了分段锁机制,改为使用一种更精细的锁策略,即每个节点或桶(bucket)上的锁。这种改进允许更多的并发操作,极大地提高了性能。
    • 对于某些操作如 get() 方法,不需要加锁即可执行,进一步提升了读操作的效率。

2. 性能

  • Hashtable
    • 因为所有方法都是同步的,所以在高并发环境下性能较差。
  • ConcurrentHashMap
    • 提供了更好的并发性能,特别是在读多写少的情况下。由于其细粒度的锁机制,允许多个线程同时对不同的段或节点进行读写操作。

3. 失效策略

  • Hashtable
    • 不支持null键或值。
  • ConcurrentHashMap
    • 同样不接受null键或值,这是为了防止潜在的歧义,例如判断一个键是否存在时,如果允许null值,则难以区分“键不存在”和“键对应的值为null”。

4. 迭代器行为

  • Hashtable
    • 它的迭代器是fail-fast的,意味着如果在创建迭代器后有其他线程修改了哈希表结构(增加或删除元素),则会抛出 ConcurrentModificationException 异常。
  • ConcurrentHashMap
    • 其迭代器是弱一致性的,不会抛出 ConcurrentModificationException。即使有其他线程正在修改哈希表,迭代器仍能遍历已有的元素,并且可能会(也可能不会)反映这些更改。

5. 并发控制

  • Hashtable
    • 采用粗粒度的同步控制,整个对象被锁定以保证线程安全性。
  • ConcurrentHashMap
    • 采用了更为先进的并发控制技术,如CAS(Compare And Swap)操作,结合锁机制来提供更高的并发性。

综上所述,虽然两者都是线程安全的集合类型,但在大多数情况下,ConcurrentHashMap 因其优秀的并发处理能力和更高的性能而成为首选。除非你需要完全的同步并且能够接受较低的性能,否则一般推荐使用 ConcurrentHashMap 而不是 Hashtable

THE END
喜欢就支持一下吧
点赞6 分享