자바에서 멀티스레드 환경을 다루다 보면 자주 듣게 되는 말이 있다.
바로 "happens-before" 관계다.
이것은 단순한 실행 순서를 말하는 게 아니다.
“스레드 간의 메모리 정합성”을 보장하는 논리적 순서의 규칙이다.
🔍 happens-before란?
happens-before는 자바 메모리 모델(Java Memory Model, JMM)에서
“A 작업이 B 작업보다 먼저 일어났음을 메모리 차원에서 보장하는 관계”를 말한다.
즉, A happens-before B라면 → A의 메모리 변경 결과는 B에서 반드시 보인다.
단순한 코드 순서가 아니라, 메모리 가시성(visibility)과 관련된 개념이다.
🧱 대표적인 happens-before 관계 6가지
동일 스레드 내 코드 순서
int x = 1;
int y = x + 1;
→ 한 스레드 안에서는 위 코드는 순차적으로 실행되며, happens-before 관계가 성립한다.
synchronized의 unlock → lock
synchronized(lock) {
shared++;
}
synchronized(lock) {
System.out.println(shared);
}
→ 첫 블럭에서의 변경 사항은 두 번째 블럭에서 반드시 보인다.
volatile write → volatile read
volatile int flag = 0;
// Thread A
flag = 1;
// Thread B
if (flag == 1) {
// 반드시 flag == 1로 보인다
}
→ volatile은 가시성(visibility)을 보장하기 때문에 메모리 정합성이 유지된다.
Thread.start() 이전 작업 → run() 내부 작업
shared = 42;
Thread t = new Thread(() -> {
System.out.println(shared); // 42 보장
});
t.start();
Thread.join() → 해당 스레드 종료 이전 작업
Thread t = new Thread(() -> {
shared = 42;
});
t.start();
t.join();
System.out.println(shared); // 42가 반드시 보임
final 필드 초기화 → 참조 가능 시점
class Person {
final String name;
Person(String name) {
this.name = name;
}
}
→ 생성자에서 초기화된 final 필드는 해당 객체가 다른 스레드에서 참조 가능해진 이후에도 안전하게 읽을 수 있다.
단, escape가 없는 경우에만 보장된다.
✅ 마무리 요약
happens-before는 단순히 코드가 "먼저 실행되었다"는 의미가 아니다.
한 작업의 메모리 결과가 다른 스레드에서 ‘반드시’ 관측될 수 있음을 보장하는 관계다.
'언어 > Java' 카테고리의 다른 글
왜 List<String>은 List<Object>가 될 수 없을까? (제네릭과 와일드카드가 공존하는 이유) (0) | 2025.05.03 |
---|---|
왜 불변 객체를 써야 할까? (0) | 2025.05.03 |
ABA 문제란? - CAS 에서 터질 수 있는 진짜 함정 (0) | 2025.05.02 |
Executor 프레임워크2 - Executor 프레임워크가 등장한 이유 (0) | 2025.04.30 |
Executor 프레임워크1 - 스레드를 직접 사용할 때 문제점 (0) | 2025.04.30 |