개발자 기술면접 꼬리물기 질문
  • Welcome
  • 01 Java
    • 01-01. Generic
    • Garbage Collection
    • 자료형과 객체 비교
    • 힙(Heap)과 메모리(Memory)
    • JDK 버전과 JRE
    • 스레드(Thread)
    • 예외(Throwable)
    • Call By Value와 Call By Reference
    • String, equals, StringBuffer
    • Thread와 비동기
  • 02 Spring
    • 02-01. Spring 동작 방식
    • @Autowired, @RequiredArgsConstructor
    • 인증(Authentication)과 인가(Authorization)
    • 트랜잭션(Transaction)
    • QueryDSL과 SQL Injection
    • SecurityContextHolder
    • @EqualsAndHashCode
  • 알고리즘과 자료구조
    • Set 자료구조
    • 정렬 알고리즘
    • 우선순위 큐 (Priority Queue)
    • DFS와 BFS
    • 힙(Heap) 자료구조
    • 스택(Stack)과 큐(Queue)
    • 암호화 알고리즘
    • LinkedList
    • 자료구조 - 해시 테이블(HashTable)
    • 자료구조 - ConcurrentHashMap
  • 데이터베이스
    • 기본
    • 인덱스 (Index)
    • 정규화 (Normalization)
    • 파티셔닝과 샤딩(Partitioning & Sharding)
    • 트랜잭션(Transaction)과 락(Lock)
    • 덤프(Dump)
    • Redis
    • 격리 수준(MySQL)
  • 네트워크
    • 전송 계층 (Transport Layer)
    • 네트워크 계층 (Network Layer)
    • Http와 Https
    • IP(Internet Protocol)
    • 프록시 서버
    • Http Protocol
    • 소켓(Socket)
    • 로드 밸런싱(Load Balancing)
  • 디자인 패턴
    • 전략 패턴 (Strategy Pattern)
    • 싱글톤 패턴 (Singleton Pattern)
    • 템플릿 메서드 패턴과 전략 패턴
    • 데코레이터 패턴 (Decorator pattern)
  • 웹
    • CORS 정책
    • 동시성 제어
    • N+1 문제
    • 웹 브라우저 동작원리
    • URI, URL, URN
    • 채팅 아키텍처 설계
  • 개발자
    • 개발 방법론 TDD
  • 운영체제
    • JIT & AOT 컴파일
    • 컨텍스트 스위칭(Context Switching)
    • 프로세스와 스레드
    • 싱글 스레드와 멀티 스레드
  • 코딩테스트
    • Stack / Queue (스택 / 큐)
    • Heap(우선 순위 큐)
    • DP(동적 계획법)
    • DFS(깊이 우선 탐색)
    • BFS(너비 우선 탐색)
    • Greedy(그리디 알고리즘)
    • 해시(Hash)
    • 투 포인터 알고리즘
    • Shortest path
    • 수학적 사고
Powered by GitBook
On this page
  • Q. HashMap을 멀티스레드 환경에서 사용하면 어떤 문제가 생기나요?
  • Q. HashMap과 ConcurrentHashMap간의 차이를 설명해주세요.
  • Q. ConcurrentHashMap에서는 왜 null key나 null value를 허용하지 않나요?
  • Race Condition이 무엇인가요?
  1. 알고리즘과 자료구조

자료구조 - ConcurrentHashMap

Q. HashMap을 멀티스레드 환경에서 사용하면 어떤 문제가 생기나요?

HashMap은 동기화가 전혀 되어 있지 않아서, 멀티스레드 환경에서 동시에 put이나 resize가 일어나면 내부 구조가 쉽게 깨집니다.

특히 문제가 되는 건 resize 과정입니다.한 스레드가 배열을 확장하고 있는 동안 다른 스레드가 동시에 put을 수행하면 연결 리스트 구조가 잘못 이어질 수 있는데요, 이 경우 무한 루프가 발생하거나, GC가 회수하지 못하는 참조가 남아서 메모리 누수나 CPU 100% 사용 같은 치명적인 문제로 이어질 수 있습니다.

이런 문제를 피하기 위해 멀티스레드 환경에서는 HashMap 대신 ConcurrentHashMap을 사용합니다.

Q. HashMap과 ConcurrentHashMap간의 차이를 설명해주세요.

HashMap은 단일 배열을 기반으로 연결 리스트나 트리 구조를 사용해서 데이터를 저장합니다. 하지만 동기화 처리가 전혀 없기 때문에 멀티스레드 환경, 예를 들어 두 스레드가 동시에 put하는 경우 등 에서는 스레드 간 충돌이 발생할 수 있습니다.

반면, ConcurrentHashMap은 멀티스레드 환경에서도 안전하게 사용할 수 있도록 설계된 Map입니다.

Java 7까지는 내부적으로 Segment라는 배열을 두고, 각 Segment마다 락을 걸어 동시 접근을 분산시켰습니다.

하지만 이 구조는 Segment 개수만큼만 병렬처리가 가능하다는 단점이 있어서, Java 8부터는 Segment를 제거하고, 각 버킷에 CAS 연산 또는 synchronized 블록을 적용하는 방식으로 개선됐습니다.

이 덕분에 읽기 연산은 락 없이 빠르게 수행되고, 쓰기 연산도 필요한 버킷에만 락을 걸기 때문에 성능과 안전성 모두 확보할 수 있습니다.

또 하나 중요한 차이는, HashMap은 null key와 null value를 허용하지만 ConcurrentHashMap은 둘 다 허용하지 않는다는 점입니다.

Q. ConcurrentHashMap에서는 왜 null key나 null value를 허용하지 않나요?

가장 큰 이유는 명확성과 안정성입니다. map에서 get(key)의 결과가 null일 때, 해당 키가 없어서 null이 반환된 건지, 아니면 실제로 value가 null인 건지 구분이 안되기 때문입니다.

이 모호함은 단일 스레드 환경에서는 containsKey()로 확인할 수 있지만, 멀티스레드 환경에선 그 사이에 다른 스레드가 값을 바꿔버릴 수 있어서 race condition이 발생할 수 있습니다.

예를 들어, 한 스레드는 put(key, null)을 수행했고, 다른 스레드는 get(key)을 호출했을 때 null이 나왔다면 두 번째 스레드는 "해당 키가 아직 저장되지 않았나?"라고 잘못 판단할 수 있습니다.

그래서 ConcurrentHashMap은 명확성과 안정성 확보를 위해 null 자체를 아예 허용하지 않도록 설계됐습니다.

Race Condition이 무엇인가요?

Race condition은 여러 스레드가 동시에 같은 자원에 접근하면서, 그 순서나 타이밍에 따라 프로그램의 결과가 달라지는 상황을 말합니다. 즉, 의도하지 않은 타이밍 문제로 인해 예측 불가능한 결과나 버그가 발생하는 상태입니다.

예를 들어, 두 개의 스레드가 동시에 같은 변수에 값을 더하려고 할 때, 각 스레드가 읽고 쓰는 순서가 엇갈리면 최종 결과가 정확하지 않을 수 있습니다. 이런 상황이 바로 race condition이고, 주로 공유 자원을 락 없이 사용할 때 발생합니다.

그래서 멀티스레드 환경에서는 synchronized, 락, Atomic 클래스 같은 동기화 기법을 사용해서 race condition을 방지해야 합니다.

Previous자료구조 - 해시 테이블(HashTable)Next기본

Last updated 16 days ago