배열과 컬렉션의 내용을 정리하던 중, ConcurrentHashMap은 좀 더 상세하게 다룰 필요가 있다고 생각해 별도 페이지로 작성했다.
ConcurrentHashMap은 Java에서 동시성 문제를 해결하기 위해 설계된 스레드 안전한 HashMap이다.
Java 1.5부터 java.util.concurrent 패키지에 포함되어 있으며, 여러 스레드가 동시에 읽고 쓸 수 있도록 특별한 락 분할 메커니즘을 사용한다.
race condition이 발생할 수 있음Hashtable이나 synchronizedMap을 사용했지만, 이들은 전체 맵에 대해 synchronized 처리를 하여 성능 병목이 생김.=> 이를 개선하고자 보다 정교하게 동기화를 제어할 수 있는 ConcurrentHashMap이 등장하였다.
race condition: 둘 이상의 스레드가 동시에 같은 자원에 접근하거나 변경하면서, 실행 순서에 따라 결과가 달라지는 문제 상황
세분화된 락(분할 락):
Java 8 이전까지는 Segment 단위로 락을 나눴고, Java 8부터는 bucket(배열의 각 요소) 단위로 동기화하여 병렬성을 높였다.
읽기 작업은 락 없이 처리
대부분의 읽기 작업은 락 없이 진행되며, 변경 작업만 최소한의 락으로 처리된다.
null key, null value 금지
null 키나 null 값을 허용하지 않으며, NullPointerException이 발생한다.
성능 중심 설계
락의 범위를 최소화하여 성능 저하 없이 스레드 안전성을 확보했다.
// Java의 AtomicInteger에서 예시
AtomicInteger count = new AtomicInteger(0);
count.compareAndSet(0, 1); // 현재 값이 0이면 1로 바꿔라contention(락 경쟁, 경합): 여러 스레드가 한개 버킷에 접근할 때 버킷의 락이 병목 지점이 돼서 여러 스레드가 대기 상태에 빠지는 상황| 컬렉션 | 스레드 안전성 | 성능 | 비고 |
|---|---|---|---|
| HashMap | X | 빠름 | 동기화 불가 |
| Hashtable | O | 느림 | 전체 메서드 동기화 |
| Collections.synchronizedMap() | O | 보통 | 단일 락 기반 |
| ConcurrentHashMap | O | 가장 빠름 | 세분화된 락, 병렬성 우수 |