Java 语言 并发集合 ConcurrentHashMap 底层 分段锁到CAS的演进

Java阿木 发布于 25 天前 3 次阅读


摘要:

Java并发集合(ConcurrentHashMap)是Java并发编程中常用的线程安全集合之一。从JDK 1.5开始,ConcurrentHashMap经历了从分段锁到CAS(Compare-And-Swap)的演进过程。本文将围绕这一主题,通过代码分析,探讨ConcurrentHashMap的底层实现,以及其从分段锁到CAS的演进原因和优势。

一、

在多线程环境下,为了保证数据的一致性和线程安全,Java提供了多种并发集合。ConcurrentHashMap作为其中的一员,其性能和线程安全性一直是开发者关注的焦点。本文将深入分析ConcurrentHashMap的底层实现,探讨其从分段锁到CAS的演进过程。

二、分段锁

在JDK 1.5之前,ConcurrentHashMap的实现基于分段锁(Segment Locking)。分段锁将整个哈希表分为若干个段(Segment),每个段维护一个锁。当一个线程访问某个段时,它需要获取该段的锁。这样,不同线程访问不同段时可以并发进行,从而提高并发性能。

以下是分段锁的简单实现代码:

java

public class ConcurrentHashMapSegmentLock {


private final Segment[] segments;

public ConcurrentHashMapSegmentLock(int initialCapacity, float loadFactor) {


this.segments = new Segment[initialCapacity];


for (int i = 0; i < segments.length; i++) {


segments[i] = new Segment();


}


}

public V put(K key, V value) {


int segmentIndex = (key.hashCode() & (segments.length - 1));


Segment segment = segments[segmentIndex];


return segment.put(key, value);


}

private static class Segment {


private final ReentrantLock lock = new ReentrantLock();


private final HashMap<K, V> hashTable = new HashMap<>();

public V put(K key, V value) {


lock.lock();


try {


return hashTable.put(key, value);


} finally {


lock.unlock();


}


}


}


}


三、CAS

随着多核处理器的普及,线程之间的竞争越来越激烈。分段锁虽然提高了并发性能,但在高并发场景下,仍然存在性能瓶颈。为了解决这一问题,JDK 1.7引入了CAS(Compare-And-Swap)算法,从而实现了ConcurrentHashMap的进一步优化。

CAS是一种无锁算法,通过比较内存中的值和预期值,如果相等,则将内存中的值更新为新的值。以下是使用CAS实现的ConcurrentHashMap的简单代码:

java

public class ConcurrentHashMapCAS {


private final Node[] table;

public ConcurrentHashMapCAS(int initialCapacity) {


this.table = new Node[initialCapacity];


for (int i = 0; i < table.length; i++) {


table[i] = new Node();


}


}

public V put(K key, V value) {


int index = (key.hashCode() & (table.length - 1));


Node node = table[index];


return node.put(key, value);


}

private static class Node {


private volatile V value;


private volatile Node next;

public V put(K key, V value) {


Node node = new Node(key, value);


while (true) {


Node next = this.next;


if (next == null) {


if (this.next = node) {


return value;


}


} else {


V oldValue = next.value;


if (next.value = value) {


return oldValue;


}


}


}


}


}


}


四、从分段锁到CAS的演进原因和优势

1. 演进原因

(1)分段锁在高并发场景下存在性能瓶颈;

(2)多核处理器环境下,线程之间的竞争加剧;

(3)CAS算法具有更高的并发性能。

2. 优势

(1)提高并发性能:CAS算法避免了锁的竞争,从而提高了并发性能;

(2)降低内存占用:CAS算法不需要为每个段维护一个锁,从而降低了内存占用;

(3)简化实现:CAS算法的实现相对简单,易于理解和维护。

五、总结

本文通过代码分析,探讨了Java并发集合(ConcurrentHashMap)从分段锁到CAS的演进过程。从分段锁到CAS的演进,不仅提高了ConcurrentHashMap的并发性能,还简化了其实现。在多核处理器环境下,ConcurrentHashMap已成为线程安全集合的首选之一。