[Java] 가시성 - volatile
Java 스터디를 진행하며 작성한 글입니다.
가시성 - volatile
이번 글에서는 votaile 키워드를 사용해 가시성을 보장하는 방법을 간단한 예와 함께 설명하려고 한다.
아래 코드를 살펴보자.
public class Volatile {
private static boolean stopRequested;
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(() -> {
int i = 0;
while (!stopRequested) {
i++;
}
});
backgroundThread.start();
Thread.sleep(1000);
stopRequested = true;
}
}
메인 스레드가 1초 후 stopRequested 변수를 true로 설정하기 때문에 backgroupdThread는 1초 후 반복문을 빠져나올 것처럼 보일 것이다. 그러나 실제로 실행시키면 위 코드는 아래처럼 반복문을 빠져나오지 못해 영원히 실행될 수도 있다.
다음 그림을 살펴보자.
CPU1에서 수행된 스레드를 backgroundThread, CPU2에서 수행된 스레드를 mainThread라고 하자. mainThread는 CPU Cache Memory 2와 RAM에 공유 변수인 stopRequested를 true로 쓰기 작업을 완료했으나, backgroundThread는 CPU Cache Memory 1에서 읽은 업데이트 되지 않은 stopRequested값을 사용한다. 이 값은 false이므로 무한 루프를 수행하게 된다. 즉, mainThread가 수정한 값을 backgroundThread가 언제쯤에나 보게 될지 보증할 수 없다. 이러한 문제점을 가시성 문제라고 한다.
이 문제를 해결하기 위해서는 stopRequested 변수를 volatile로 선언하면 된다. 그럼 다음 그림과 같이 CPU Cache Memory를 거치지 않고 RAM으로 직접 읽고 쓰는 작업을 수행하게 된다.
변경된 코드도 살펴보자.
public class Volatile {
private static volatile boolean stopRequested;
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(() -> {
int i = 0;
while (!stopRequested) {
i++;
}
});
backgroundThread.start();
Thread.sleep(1000);
stopRequested = true;
}
}
코드를 실행시키면 1초 후 프로그램이 종료되는 것을 확인할 수 있다.
참고
- https://badcandy.github.io/2019/01/14/concurrency-02/
- https://ecsimsw.tistory.com/entry/자바의-동기화-방식-메모리-가시성이란-synchronized-volatile-atomic
예상 면접 질문 및 답변
링크 참고
'프로그래밍 언어 > Java' 카테고리의 다른 글
[Java] Thread 문법 총 정리 (0) | 2022.01.22 |
---|---|
[Java] 원자성 - Atomic Type (0) | 2022.01.08 |
[Java] 자바의 동시성 이슈 (0) | 2022.01.08 |
[Java] 뮤텍스, 세마포어와 모니터 (0) | 2022.01.08 |
[Java] 동기화 - synchronized (0) | 2021.12.21 |
댓글