728x90
반응형
SMALL
왜 알아야 할까?
- 여러 스레드가 동시에 공유 변수를 읽고 쓸 때, 값이 예상대로 보장되지 않는 문제가 생긴다.
- Java는 성능 최적화를 위해 JVM 레벨에서 변수 캐싱이나 명령어 재정렬(reordering) 을 수행한다.
- 이런 최적화는 단일 스레드에서는 효과적이지만, 멀티스레드에서는 데이터 불일치를 초래한다.
예시: 잘못된 멀티스레드 동작
public class VisibilityProblem {
static boolean isRunning = true;
public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
while (isRunning) {
// isRunning 값이 변경되었는지 확인하려고 함
}
System.out.println("스레드 종료");
}).start();
Thread.sleep(1000);
isRunning = false;
System.out.println("isRunning을 false로 변경");
}
}
예상 출력:
isRunning을 false로 변경 후 스레드 종료
실제 출력:
스레드 종료가 출력되지 않음
이유? → isRunning은 스레드 내 CPU 캐시에만 저장되어 다른 스레드의 변경을 감지하지 못함
해결법: volatile 사용
static volatile boolean isRunning = true;
- volatile을 붙이면 모든 스레드가 메인 메모리의 값을 참조하도록 강제한다.
- 가시성(visibility) 은 보장되지만, 원자성(atomicity) 은 보장하지 않는다.
volatile의 한계
static volatile int count = 0;
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(2);
for (int i = 0; i < 1000; i++) {
executor.execute(() -> count++);
}
executor.shutdown();
Thread.sleep(1000);
System.out.println("count = " + count);
}
결과: count < 1000
- 이유: count++는 읽기 → 증가 → 쓰기의 복합 연산. 이 전체가 원자적이지 않음
- 해결법: AtomicInteger 사용
AtomicInteger count = new AtomicInteger(0);
count.incrementAndGet(); // 원자적 증가
volatile vs synchronized 차이
항목
|
volatile
|
synchronized
|
가시성
|
✅ 보장
|
✅ 보장
|
원자성
|
❌ 보장 안됨
|
✅ 보장
|
성능
|
빠름
|
느림
|
락(lock) 사용
|
❌ 없음
|
✅ 있음
|
정리
- volatile은 가시성 문제 해결에만 유효하다.
- 복잡한 연산이나 데이터 무결성이 중요한 경우, synchronized 또는 java.util.concurrent 패키지를 써야 한다.
- Java Memory Model은 이런 동작이 정의된 기본 규약이며, 이를 잘 이해하면 스레드 간 충돌, 버그를 막을 수 있다.
학스의 개발일지
일상과 코딩 그 사이 어딘가에있는 블로그.. 블로거이자 빅데이터개발자 학스 입니다 JAVA, jQuery, PostgreSQL, MySQL, HIVE, Hadoop 더 많은 정보는 깃허브 주소 https://github.com/hacs2772 를 방문해주세요
hacs2772.tistory.com
728x90
반응형
LIST
'TIPS' 카테고리의 다른 글
CompletableFuture — 자바의 현대적 비동기 프로그래밍 (1) | 2025.06.16 |
---|---|
ThreadLocal — 스레드별로 고립된 변수 저장소 만들기 (6) | 2025.06.09 |
ReentrantLock vs synchronized — 자바 락의 실전 비교 (2) | 2025.06.02 |
자바에서 volatile, synchronized, AtomicInteger 언제 써야 할까? (0) | 2025.05.26 |
자바에서 불변 객체(Immutable Object)의 중요성과 정의 (0) | 2025.05.19 |