728x90
반응형
HashMap vs ConcurrentHashMap - 실시간 채팅 프로젝트에서 왜 ConcurrentHashMap을 사용하나?
HashMap 이란?
HashMap은 Java의 Map 인터페이스를 구현한 대표적인 자료 구조로, Key의 hashCode() 값을 이용해 데이터를 빠르게 저장하고 검색할 수 있습니다.
장점
- 빠른 성능 : 평균적으로 O(1)의 시간복잡도로 검색, 삽입, 삭제가 가능합니다.
- 단일 스레드 환경에서 최적 : 멀티스레드 처리를 고려하지 않을 경우, 가장 빠르고 효율적인 Map입니다.
단점
- 스레드에 안전하지 않음
- 여러 스레드가 동시에 접근할 경우, 예외 발생 및 데이터 정합성 문제가 발생할 수 있습니다.
- 발생 가능한 문제
- ConcurrentModificationException : 반복 도중 다른 스레드가 구조를 바꾸면 예외 발생합니다.
- 데이터 손실 : 동시 쓰기 시 값 덮어쓰이거나 누락될 수 있습니다.
Map<String, String> userMap = new HashMap<>();
userMap.put("id1", "Alice");
userMap.put("id2", "Bob");
String name = userMap.get("id1");
ConcurrentHashMap 이란?
ConcurrentHashMap은 Java에서 제공하는 멀티스레드 환경에 안전하게 동작하는 Map 구현체입니다.
Map<String, String> map = new ConcurrentHashMap<>();
map.put("user1", "session1");
장점
- Thread-safe : 여러 스레드가 동시에 접근해도 데이터 충동 없이 안전하게 동작합니다.
- 높은 성능 유지 : 전체를 동기화하지 않고, 버킷 단위로 락을 걸어 경합 최소화 합니다.
- 원자적 연산 지원 : pubIfAbsent, computerIfAbsent, merge 같은 메서드를 통해 동시성 문제없는 연산이 가능합니다.
내부 동작 방식
연산 | 동작방식 |
get() | 락 없이 동작 |
put(), remove() | 해당 버킷 부분 락 |
computer() | CAS 기반 낙관적 락 방식 일부 사용 |
1. 실시간 채팅에서 ConcurrentHashMap이 필요한 이유
private final Set<String> sessions = ConcurrentHashMap.newKeySet();
- 동시에 여러 사용자가 접속/이탈 해도 안전하게 세션 관리 가능합니다.
- 내부적으로는 ConcurrentHashMap<String, Boolean> 기반의 KeySetView
- 스레드 간 충돌 없이 sessionId 저장 및 삭제 가능합니다.
2. 일반 HashSet/HashMap을 사용할 경우 문제점
실시간 채팅에서는 여러 사용자가 동시에 다음과 같은 상황 발생합니다.
- 동시에 여러 사용자가 접속 할 때 - connectHandle
- 동시에 여러 사용자가 연결 종료 할 때 - disconnectHandle
이때 일반 HashSet, HashMap을 사용했다면?
private final Set<String> sessions = new HashSet<>(); // 위험
- 이 구조는 동시 접근시 ConcurrentModificationException 발생 가능성 있습니다.
- 또는 세션 ID가 정상적으로 추가/삭제되지 않아 메모리 누수가 발생합니다.
- 심지어 동일한 세션 ID가 중복 저장되어 서버 리소스 낭비 가능합니다.
3. ConcurrentHashMap.newKeySet()의 장점
ConcurrentHashMap<String, Boolean> backingMap = new ConcurrentHashMap<>();
Set<String> threadSafeSet = backingMap.keySet();
- 다중 스레드 환경에서 안전하게 add/remove 가능합니다.
- 현재 접속 중인 사용자 수를 정확히 파악할 수 있습니다.
- 부분 락 및 lock-free 접근 덕분에 성능 저하 없습니다.
- 세션 누수 없이 안정적인 메모리 관리 가능합니다.
728x90
반응형
'JAVA' 카테고리의 다른 글
IS-a와 HAS-a 관계 (0) | 2025.04.25 |
---|---|
인터페이스와 추상클래스 (0) | 2025.04.10 |
팩토리 메서드 패턴 (0) | 2025.02.17 |