ConcurrentHashMap이란

오정빈·2025년 9월 10일

내일배움캠프

목록 보기
8/22

2025 09 10 스파르타 코딩클럽 8일차

오늘은 전에 사둔 spring 강의를 마저 보면서 새로운 해시맵인 ConcurrnetHashMap을 알게 되어서 ConcurrnetHashMap이 무엇인지 알아볼 것이다.


1. Map 소개

Map은 Java 컬렉션 프레임워크의 인터페이스로, 키(Key)와 값(Value) 쌍을 저장하는 자료구조입니다.

  • 키는 유일(unique)해야 하고, 값은 중복될 수 있습니다.
  • 대표적인 메서드:
    • put(key, value) : 데이터 추가
    • get(key) : 키에 해당하는 값 조회
    • remove(key) : 데이터 삭제
    • containsKey(key) : 특정 키 존재 여부 확인

2. Map의 주요 구현체

Java에는 다양한 Map 구현체가 존재하며, 각기 다른 특성과 사용 목적이 있습니다.

(1) HashMap

  • 가장 일반적으로 사용되는 Map 구현체
  • 해시 테이블을 기반으로 데이터 저장
  • 순서를 보장하지 않음
  • null 키 1개와 null 값 여러 개 허용

(2) LinkedHashMap

  • 입력된 순서(또는 접근 순서)를 유지
  • 순서 보장이 필요한 경우 사용

(3) TreeMap

  • 키를 자동으로 정렬 (기본은 오름차순)
  • 내부적으로 Red-Black Tree 사용
  • 범위 검색이나 정렬이 필요할 때 적합

(4) Hashtable

  • HashMap과 유사하지만, 모든 메서드가 동기화 처리됨
  • 레거시 클래스라 잘 사용하지 않음

(5) ConcurrentHashMap

  • 멀티스레드 환경에서 안전한 Map
  • Hashtable보다 효율적 (버킷 단위로 락을 걸어 성능 향상)
  • null 키와 null 값은 허용하지 않음

3. ConcurrentHashMap 소개

특징

  • 스레드 안전(Thread-safe)
    여러 스레드가 동시에 접근해도 데이터가 깨지지 않음
  • 부분 락(lock striping)
    전체 맵이 아니라 일부 버킷에만 락을 걸어 성능을 높임
  • 읽기 연산은 락 없이
    대부분의 get()은 락 없이 진행 → 빠른 조회 가능
  • null 불가
    null 키와 null 값은 허용하지 않음

언제 사용할까?

  • 멀티스레드 환경에서 공유 데이터를 저장/조회할 때
  • 동시성 문제가 생기지 않으면서 빠른 성능이 필요한 경우
  • 예: 캐시(Cache) 시스템, 스레드 간 데이터 공유

4. 코드 예시

import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMapExample {
    public static void main(String[] args) {
        // ConcurrentHashMap 생성
        ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

        // 데이터 추가
        map.put("apple", 10);
        map.put("banana", 20);

        // 데이터 조회
        System.out.println("apple: " + map.get("apple")); // apple: 10

        // 값 수정 (동기적으로 안전하게 처리)
        map.compute("apple", (k, v) -> v + 1);
        System.out.println("apple after update: " + map.get("apple")); // apple after update: 11

        // 키 존재 여부 확인
        if (map.containsKey("banana")) {
            System.out.println("banana exists!");
        }

        // 멀티스레드 환경에서 안전하게 접근 가능
        Runnable task = () -> {
            for (int i = 0; i < 5; i++) {
                map.merge("banana", 1, Integer::sum);
            }
        };

        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);
        t1.start();
        t2.start();
    }
}

0개의 댓글