Java Memory Model (JMM)의 happens-before 관계에 대해 설명하고, volatile 키워드가 JMM 관점에서 어떻게 가시성(visibility)과 순서(ordering)를 보장하는지 내부 동작 원리를 상세히 설명해 주십시오.
힌트 · JMM은 스레드 간 메모리 가시성 규칙을 정의합니다. volatile은 read/write 시 memory barrier를 삽입하여 컴파일러 및 CPU의 재정렬을 방지하고 캐시 일관성을 보장합니다.
모범답안
Java Memory Model (JMM)의 happens-before 관계는 한 스레드 내의 연산 순서뿐 아니라 스레드 간의 연산 순서에 대한 규칙을 정의합니다. A happens-before B라면, A의 결과가 B에게 반드시 보여지는 것을 보장합니다. 즉, A가 B보다 먼저 실행된 결과를 B가 볼 수 있다는 의미입니다.
volatile 키워드는 JMM 관점에서 변수의 가시성과 순서화를 보장합니다. volatile 변수에 대한 쓰기 연산은 항상 메인 메모리에 직접 쓰여지고, 읽기 연산은 항상 메인 메모리에서 읽어옵니다. 이는 각 CPU 코어의 캐시에 저장된 값을 무시하고, 항상 최신 값을 사용하도록 강제합니다.
내부적으로 volatile은 읽기/쓰기 연산 앞뒤에 메모리 배리어(Memory Barrier)를 삽입합니다. 쓰기 배리어는 쓰기 연산이 캐시에만 머무르지 않고 메인 메모리에 즉시 반영되도록 하고, 읽기 배리어는 캐시에서 값을 읽지 않고 메인 메모리에서 최신 값을 읽어오도록 합니다. 이러한 메모리 배리어는 컴파일러와 CPU의 명령어 재정렬을 막아, volatile 변수에 대한 연산 순서가 프로그램 코드에 명시된 순서대로 실행되도록 보장합니다. 결과적으로 volatile은 스레드 간 데이터 경쟁 상황을 방지하고, 예측 가능한 동시성 프로그래밍을 가능하게 합니다.
읽었다면, 이제 직접 답해볼 차례예요
패스잇 앱에서 이 질문에 말로 답하면 AI가 꼬리질문까지 이어가며 1:1 코칭합니다.
함께 보는 동시성 / 멀티스레딩 면접 질문
- 스레드 풀(Thread Pool)을 사용하는 주된 이유와 이점이 무엇인지 설명해주세요. 스레드 풀의 크기를 결정할 때 고려해야 할 요소들과, 잘못된 스레드 풀 사용으로 발생할 수 있는 문제점들을 함께 설명해주세요.
- 동시성 프로그래밍에서 불변 객체(Immutable Object)가 갖는 장점은 무엇이며, 어떻게 불변 객체를 설계하여 스레드 안전성을 높일 수 있는지 구체적인 방법을 설명해주세요. 단점이나 제약 사항도 있다면 함께 언급해주세요.
- 멀티스레딩 환경에서 문맥 교환(Context Switching)이 발생하는 시점과 그 과정에 대해 설명해주세요. 문맥 교환이 시스템 성능에 미치는 영향은 무엇이며, 이를 최소화하기 위한 방법에는 어떤 것들이 있는지 설명해주세요.
- 락(Lock)을 사용하지 않고 스레드 안전한(thread-safe) 큐를 구현한다고 가정할 때, 어떤 기법들을 활용할 수 있으며, 특히 CAS(Compare-And-Swap) 연산을 사용하여 어떻게 원자성(atomicity)을 보장할 수 있는지 구체적인 예시와 함께 설명해 주십시오. 락 프리(lock-free) 방식의 장단점은 무엇입니까?
- 멀티스레드 환경에서 캐시 일관성(cache coherence)과 관련된 문제 중 'False Sharing'이 무엇인지 설명하고, 이로 인해 발생하는 성능 저하 문제를 어떻게 진단하고 해결할 수 있는지 구체적인 방안을 제시해 주십시오.
- 분산 시스템 또는 복잡한 마이크로서비스 환경에서 발생할 수 있는 교착 상태(deadlock)를 예방하거나 탐지하기 위한 고급 전략에는 어떤 것들이 있으며, 각 전략의 구현 복잡도와 실제 적용 시의 고려사항은 무엇인지 설명해 주십시오.