멀티스레드 프로그래밍은 여러 스레드가 동시에 실행되는 환경을 말한다. 한 어플리케이션 내에서 동시에 여러 작업을 처리할 수 있게 해주지만, 공유 자원에 대한 접근과 수정에서 동시성 문제를 야기할 수 있다. 이런 문제들을 해결하기 위해서는 스레드 간의 적절한 조정과 자원 관리가 필요합니다.
Volatile 키워드란?
자바에서 volatile 키워드는 변수를 메인 메모리에 저장하게 함으로써, 모든 스레드가 항상 최신의 변수 값을 보게 하는 역할을 한다. 일반 변수가 스레드의 로컬 캐시에 저장되어 값의 불일치가 발생할 수 있는 것과 달리, volatile 변수는 메모리 가시성을 보장한다.
메모리 가시성(Memory Visibility)은 한 스레드에 의해 변경된 데이터가 다른 스레드에게 얼마나 빠르고 정확하게 보이느냐를 의미한다. volatile 키워드를 사용함으로써 모든 스레드는 해당 변수에 대한 최신 값을 메인 메모리에서 직접 읽게 되는것이다.
멀티스레드 환경에서의 Volatile, 사용 방법
public class Test {
volatile boolean flag = true; // volatile을 사용하면 같은 flag 변수를 바라본다
public void test() {
new Thread(()->{ // T1
int cnt = 0;
while (flag) {
cnt++;
}
System.out.println("Thread1 finished\n");
}
).start();
new Thread(()-> { // T2
// T1과 T2는 같은 변수 flag를 바라보고
// T2의 flag = false; 로직이 실행될때 T1의 while문이 중지된다고 생각할 수 있지만 무한루프를 돌게된다
// 이유는 두 쓰레드의 flag 변수는 캐시메모리로 각각 할당이 되기 때문이다
try {
Thread.sleep(100);
} catch (InterruptedException ignored) {
}
System.out.println("flag to false");
flag = false;
}
).start();
}
public static void main(String[] args) {
new Test().test();
}
}
volatile은 주로 상태 플래그나 특정 조건의 변경을 다른 스레드에게 신속하게 알려야 할 때 사용된다. 예를 들어, 한 스레드가 실행 중인지를 체크하는 플래그 같은 간단한 상황에서 유용하다.
Volatile과 Synchronized의 비교
volatile은 변수의 동시성 접근에 대한 가시성만을 보장하지만, synchronized는 스레드 간의 동기화와 상호 배제(mutual exclusion)를 보장한다. volatile은 상태 플래그에 적합하지만, 복잡한 상태의 일관성을 유지해야 하는 경우에는 synchronized나 다른 동시성 메커니즘이 더 적합할 수 있다.
Volatile 사용시 주의사항
volatile은 변수의 원자적인 읽기와 쓰기는 보장하지만, 복합적인 연산(예: count++)에서는 원자성을 보장하지 않는다. 이런 경우 추가적인 동기화 조치가 필요하다.
'Java, Spring' 카테고리의 다른 글
| Spring의 이벤트 리스너 비교: @EventListener vs @TransactionalEventListener (0) | 2025.04.01 |
|---|---|
| [Spring Boot] 스프링부트 JDBC logging 파헤치기 (로그설정, 로그레벨, JPA 쿼리) (0) | 2023.11.27 |
| [Java] 순차 스트림 (Sequential Stream)과 병렬 스트림 (Parallel Stream) & 스레드로 처리하기 (0) | 2023.11.14 |
| [JPA] Spring 3.0에서 queryDSL q파일 재생성하기(gradle) (0) | 2023.09.15 |
| [JPA] Entity->DTO, DTO->Entity 간의 매핑을 편리하게 해주는 MapStruct (0) | 2023.09.08 |