Java / JVMintermediate검토 2026.08

메모리 가시성

한 Thread가 바꾼 값을 다른 Thread가 언제 관찰할 수 있는지 설명한다.

#JMM#volatile#happens-before

Overview

공유 변수를 변경했다는 사실과 다른 Thread가 변경을 관찰한다는 사실은 같지 않다.

핵심 원리

happens-before 관계가 변경의 공개와 관찰 순서를 정의한다. volatile은 가시성을 제공하지만 복합 연산 전체의 원자성을 보장하지 않는다.

flowchart LR; A[Thread A 변경] --> B[동기화 경계]; B --> C[Thread B 관찰]
메모리 가시성 동작 흐름

실무에서 발생하는 문제

동기화 없이 공유한 Flag는 다른 Thread에서 갱신이 늦게 보이거나 복합 상태의 일부만 보일 수 있다. 재현 빈도가 낮아 Test를 통과해도 운영 CPU와 최적화 조건에서 드러난다.

Trade-off

volatile은 읽기·쓰기 가시성과 순서 관계를 제공하지만 복합 연산의 상호 배제는 주지 않는다. Lock은 더 넓은 상태를 보호하지만 Blocking 비용이 있다.

흔한 오해

Cache를 매번 비우는 단순 기능으로 이해하면 안 된다. 핵심은 Java Memory Model의 happens-before 관계이며 volatile++은 여전히 원자적이지 않다.

Interview Questions

  • 이 기술이 해결하는 핵심 문제는 무엇인가?
  • 내부에서는 어떤 순서로 동작하는가?
  • 운영 환경에서 어떤 지표와 실패 모드를 확인해야 하는가?

왜 필요한가

각 CPU Core와 Compiler가 읽기·쓰기를 최적화하므로 한 Thread의 변경이 다른 Thread에 언제 보이는지 규칙이 필요하다. 종료 Flag, 안전한 객체 공개, Double-checked Locking이 대표 사례다.

내부 동작

volatile Write 이전 작업은 같은 변수의 이후 Read를 수행한 Thread에 happens-before 된다. Monitor Unlock→Lock, Thread start/join, Concurrent Collection도 각자의 관계를 만든다. 가시성, 원자성, 순서성은 구분해야 한다.

Example

volatile boolean running은 한 Thread가 false를 썼을 때 Loop Thread가 변경을 관찰하게 한다. 그러나 volatile int count의 증가는 읽기와 더하기, 쓰기의 세 단계라 증가분을 잃을 수 있어 Atomic 또는 Lock이 필요하다.

Production Considerations

공유 Mutable State를 최소화하고 상태를 보호하는 단일 규칙을 문서화한다. Thread Dump와 JFR로 멈춤·경쟁을 확인하되 가시성 Bug는 Dump 하나로 증명하기 어려우므로 동시성 Test와 설계 검토를 병행한다.

CAS, synchronized, Thread 생명주기와 연결된다.

SOURCE REFERENCES

이 문서의 근거

본문은 Dev Atlas 안에서 완결되며, 검증이 필요할 때만 원문을 확인할 수 있습니다.

원문 출처 보기 2