본문 바로가기
language/java

Thread-safe 컬렉션 완벽 이해하기

by 죄니안죄니 2026. 5. 29.
반응형

Thread-safe 컬렉션 완벽 이해하기

이전 글에서:

  • synchronized
  • volatile
  • CAS
  • AtomicInteger

를 배웠습니다.

그런데 실무에서는 숫자 하나만 공유하는 경우보다

 
List
Map
Set
 

같은 컬렉션을 여러 스레드가 동시에 사용하는 경우가 훨씬 많습니다.

문제는:

 
ArrayList
HashMap
HashSet
 

은 기본적으로

Thread-Safe 하지 않다.
 

입니다.


1. Thread-Safe란?

한 줄 정의.

여러 Thread가 동시에 접근해도
데이터가 깨지지 않는 것
 

2. ArrayList 예제

 
List<Integer> list =
        new ArrayList<>();
 

Thread A

 
list.add(1);
 

Thread B

 
list.add(2);
 

동시에 실행.


3. 문제

ArrayList 내부.

 
elementData[size] = value;
size++;
 

실제로는 여러 단계.


4. Race Condition 발생

예:

size=5
 

Thread A

size 읽음
=5
 

Thread B

size 읽음
=5
 

Thread A

5번 인덱스 저장
 

Thread B

5번 인덱스 저장
 

결과

데이터 유실
 

가능.


5. HashMap도 위험

예:

 
Map<String, String> map =
        new HashMap<>();
 

여러 Thread가

 
put()
 

동시 실행.


6. 실제 문제

예전 JDK 7 시절에는

무한 루프
 

까지 발생 가능.


지금도

데이터 손실
 
읽기 오류
 

가능.


7. 그래서 등장

Thread-safe 컬렉션.


대표적으로:

 
Vector

Collections.synchronizedList()

CopyOnWriteArrayList

ConcurrentHashMap

ConcurrentLinkedQueue
 

8. 첫 번째: Vector

옛날 Java.


 
Vector<String> vector =
        new Vector<>();
 

9. 내부

사실상

 
public synchronized boolean add(...)
 

모든 메서드에

 
synchronized
 

적용.


10. 장점

안전.


11. 단점

느림.


모든 연산.

Lock
 ↓
실행
 ↓
Unlock
 

12. 그래서 실무

거의 안 씀.


13. Collections.synchronizedList

기존 List 감싸기.


 
List<String> list =
    Collections.synchronizedList(
        new ArrayList<>()
    );
 

14. 내부 구조

 
synchronized(lock) {

}
 

로 감싸는 Wrapper.


15. 장점

간단.


16. 단점

Vector와 비슷.


모든 연산 Lock.


17. 반복문 문제

매우 중요.


 
for(String s : list) {

}
 

이건 안전할까?


18. 정답

아니다.


19. 공식 문서 권장

 
synchronized(list) {

    Iterator<String> it =
        list.iterator();

    while(it.hasNext()) {

    }
}
 

반복 전체를 Lock 해야 함.


20. 그래서 등장

CopyOnWriteArrayList.


21. CopyOnWriteArrayList란?

CopyOnWriteArrayList


이름 그대로.

쓰기 시 복사
 

22. 동작 방식

현재 배열.

[A B C]
 

add(D)


새 배열 생성.

[A B C D]
 

교체.


23. 장점

읽기 매우 빠름.


락 거의 없음.


24. 반복 중 수정 가능

 
for(...) {

}
 

중에도

 
list.add(...)
 

가능.


예외 안 남.


25. 단점

쓰기 비쌈.


추가할 때마다.

배열 복사
 

발생.


26. 언제 사용?

읽기 99%
쓰기 1%
 

환경.


예:

설정값
캐시 목록
리스너 목록
 

27. ConcurrentHashMap 등장

실무 최강.


ConcurrentHashMap


28. 왜 등장?

HashMap

빠름
 

하지만

Thread-Safe 아님
 

Hashtable

안전
 

하지만

너무 느림
 

중간 해법.

ConcurrentHashMap
 

29. 사용

 
Map<String, String> map =
    new ConcurrentHashMap<>();
 

30. JDK 7 구조

예전에는.

Segment
 

기반.


Map
 ├─ Segment1
 ├─ Segment2
 ├─ Segment3
 

부분 Lock.


31. JDK 8 이후

현재 구조.


CAS
+
synchronized
 

조합.


32. 핵심 아이디어

전체 Lock 안 함.


필요한 Bucket만 Lock.


33. 장점

동시성 매우 좋음.


읽기 대부분 Lock 없음.


34. put()

경쟁 없으면

CAS
 

사용.


경쟁 심하면

synchronized
 

사용.


35. 그래서 빠름

HashTable보다 훨씬 빠름.


36. 실무 표준

멀티스레드 Map.


대부분

 
ConcurrentHashMap
 

사용.


37. ConcurrentLinkedQueue

큐 버전.


ConcurrentLinkedQueue


38. 특징

Lock-Free.


내부적으로

CAS
 

사용.


39. 사용

 
Queue<String> queue =
        new ConcurrentLinkedQueue<>();
 

40. BlockingQueue

실무 중요.


대표:

 
LinkedBlockingQueue
ArrayBlockingQueue
 

41. 특징

데이터 없으면.

자동 대기
 

생산자-소비자 패턴.


Producer
 ↓
Queue
 ↓
Consumer
 

42. Thread-safe 컬렉션 비교


컬렉션 Thread-Safe 특징
ArrayList X 일반
HashMap X 일반
Vector O 전체 Lock
synchronizedList O Wrapper
CopyOnWriteArrayList O 읽기 최적화
ConcurrentHashMap O 실무 표준
ConcurrentLinkedQueue O Lock-Free

43. 실무 사용 빈도

압도적.

ConcurrentHashMap
 

그 다음.

CopyOnWriteArrayList
 

BlockingQueue
 

44. 면접 단골 질문

Q. HashMap은 Thread-Safe인가?

아니오
 

Q. Vector는 왜 잘 안 쓰나요?

모든 연산 Lock
 

Q. ConcurrentHashMap은 어떻게 빠른가요?

전체 Lock 안 함

CAS + 부분 Lock 사용
 

Q. CopyOnWriteArrayList 특징은?

읽기 빠름

쓰기 느림
 

Q. 실무에서 Thread-Safe Map은?

 
ConcurrentHashMap
 

45. 핵심 흐름 요약

ArrayList
HashMap

↓

멀티스레드 문제

↓

Vector
synchronizedList

↓

성능 문제

↓

CAS 기반

ConcurrentHashMap
CopyOnWriteArrayList
ConcurrentLinkedQueue
 

46. 가장 중요한 핵심 한 줄

Thread-safe 컬렉션은 여러 스레드가 동시에 접근해도 데이터 무결성을 보장하는 컬렉션이며, 실무에서는 ConcurrentHashMap이 가장 널리 사용된다.
 

47. 다음 글 예고

다음 글은:

ExecutorService

입니다.

여기서부터는:

 
new Thread(...)
 

를 실무에서 거의 안 쓰는 이유,

그리고

ThreadPool
↓
ExecutorService
↓
Future
↓
CompletableFuture
 

로 이어지는 현대 Java 동시성의 핵심 구조를 배우게 됩니다.

반응형

댓글