IT/JAVA

ConcurrentHashMap – 멀티스레드 환경에서 안전하게 Map 사용하기

iamhyeon 2025. 7. 24. 16:09

Java에서 HashMap은 단일 스레드에서는 빠르게 작동하지만, 멀티스레드 환경에서는 안전하지 않다.
여러 스레드가 동시에 put()이나 get()을 호출하면 데이터 손상, ConcurrentModificationException, 무한 루프 같은 심각한 문제가 발생할 수 있다.

 

HashMap의 멀티스레드 한계

Map<String, String> map = new HashMap<>();
  • 스레드 간 동기화가 없기 때문에 동시 접근 시 데이터 충돌 가능성이 있다
  • 최악의 경우 Iterator 사용 중 ConcurrentModificationException이나 무한 루프도 일어난다.

 

ConcurrentHashMap – 안전하고 빠른 멀티스레드 Map

  • 스레드 안전(Thread-safe): 여러 스레드가 동시에 접근해도 안전
  • 높은 병렬성: 내부적으로 버킷(bin) 단위로 동기화 → 성능 최적화
  • null 금지: key, value 모두 허용 X (null 입력 시 NPE)
  • JDK 1.8부터는 Bin 기반 락, 이전 버전은 Segment 기반

 

내부 동작 원리

① 초기 설계 (JDK ≤1.7)

  • 데이터를 여러 세그먼트로 분할
  • 각 세그먼트마다 독립 락 → 세그먼트 단위 병렬성 확보

② 개선된 구조 (JDK ≥1.8)

  • Bin(버킷) 단위 락 + CAS, volatile 활용한 비차단 동기화
  • 동시성 수준 높은 읽기/쓰기 가능 

 

핵심 API 사용법

ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
map.put("apple", 1);
map.computeIfAbsent("orange", key -> 3);
map.replace("banana", 2, 20);
map.forEach((k, v) -> System.out.println(k + " : " + v));
  • computeIfAbsent, putIfAbsent, replace 등 원자적(operation atomic) 연산 제공
  • null key/value 입력 시 즉시 NullPointerException

 

동작 비교 

  HashMap  Hashtable   synchronizedMap ConcurrentHashMap
Thread-Safety ✅ (모두 락) ✅ (전체 락) ✅ (부분 락 고성능)
null 허용
성능 빠름 느림 중간 빠름
동시성 수준 없음 없음 전체 락 버킷 단위 병렬성

 

ConcurrentHashMap 완전한 해결책은 아니다

  • containsKey + put 같은 결합된 연산은 여전히 경쟁 상태(race condition) 취약하다
  • 이런 경우 putIfAbsent, computeIfAbsent 등의 atomic 메서드 사용이 필수다 

 

null value 금지

  • map.put(null, x) 또는 map.put(k, null) 시 즉시 예외 발생

 

iterator 사용 시

  • forEach 같은 내부 반복 메서드는 안전하지만
  • iterator() 사용 중 구조 변경 시 예측 불가한 결과 나올 수 있음 (예: 중복, 누락) 

 

예시

  • 캐시 구현: Spring Cache의 기본 구현체에서 ConcurrentHashMap 활용 
  • 세션 저장소, 통계 집계, 횟수 카운팅
  • 멀티스레드 서버, 이벤트 처리 루프, 스케줄러 동시 실행 환경 등 

 


  • 단일 스레드 환경에서는 HashMap도 충분하지만,
  • 멀티스레드 환경에서는 보장된 동시성(Hashtable, synchronizedMap)보다
    → ConcurrentHashMap이 부분 락 + CAS 기반으로 더 효율적이다
  • 그러나 putIfAbsent, compute* 같은 atomic 메서드를 사용해야 경쟁 조건 방지 가능하며,
  • iterator 사용 중 중복/누락 발생할 수 있음에 주의해야 한다

 

반응형

'IT > JAVA' 카테고리의 다른 글

Java 예외: RuntimeException  (0) 2025.12.06
동기화 vs 원자적 연산  (1) 2025.07.24
Java String 클래스  (0) 2025.04.15
JMH (JMH 라이브러리를 활용한 Java 코드 성능테스트)  (2) 2025.04.11
ArrayList vs LinkedList  (0) 2025.04.08