ConcurrentHashMap的性能之所以比HashTable好

145 阅读2分钟

ConcurrentHashMap的性能之所以比HashTable好,主要归因于以下几个关键设计差异:

  1. 锁的粒度不同

    • HashTable:使用的是传统的线程同步机制,即在整个HashTable上加锁(使用synchronized关键字)。这意味着在同一时刻,只能有一个线程能够执行写操作,即使读操作也要互斥等待。这导致在高并发环境下性能大幅度降低,因为所有操作必须串行执行。

    • ConcurrentHashMap:采用了**分段锁(Segmentation)**的设计思想。在Java 7及以前的版本中,ConcurrentHashMap将数据划分为多个Segment(默认为16个),每个Segment都继承自ReentrantLock,因此当对一个Segment进行写操作时,只会锁住这个Segment,其他Segment可以继续服务读写请求。这极大地减少了锁的竞争,提高了并发能力。在Java 8及以后,虽然Segment的概念被摒弃,转而使用更精细的CAS(Compare-and-Swap)操作加上若干个锁粒度更细的Node,但核心思想依然是减少锁的范围,提高并发度。

  2. 读操作无锁

    • 在ConcurrentHashMap中,读取操作通常是无锁的,这意味着读取可以和写入操作并行进行,进一步提升了并发读的性能。
  3. 扩容机制

    • HashTable在扩容时需要锁定整个表,这是一个耗时的操作,会导致所有线程阻塞。
    • ConcurrentHashMap在Java 7中采用了一种称为增量扩容的技术,即使在扩容过程中也能保证一定程度上的并发读写。而在Java 8中,更是优化了这一过程,通过CAS操作和新的节点插入逻辑,几乎实现了并发扩容,极大地减少了扩容带来的性能影响。
  4. 现代CPU架构优化

    • ConcurrentHashMap的设计考虑到了现代多核处理器的特性,通过减少伪共享(False Sharing)等问题,更好地利用了硬件资源。

综上所述,由于采用了更先进的并发控制技术和细粒度的锁设计,ConcurrentHashMap能够在多线程环境中提供更高的吞吐量和更低的延迟,因此其性能优于传统的HashTable。