[Java] volatile 키워드

sinryuji·2025년 3월 1일
post-thumbnail

출처: https://deavid.wordpress.com/2020/02/11/cpu-cache-and-memory-bottleneck/

CPU에는 Cache라는 것이 존재합니다. CPU가 항상 메모리에 있는 데이터를 사용하게 되면 저 Memory Bus를 통해야 하기 때문에 시간이 오래 걸립니다. 그렇기에 CPU는 자주 사용하는 데이터를 Cache에 복사하여 저장을 해놓고 사용을 하게 됩니다.

Java에서는 여러개의 스레드가 열리면 변수를 메인 메모리(RAM)으로 부터 가져오지 않고 각 CPU의 Cache에서 가져오게 됩니다. 이럴 때 생기는 문제점들이 있습니다.

public class Test {
    boolean flag = true;

    public void test() {
        new Thread(()->{
                int cnt = 0;
                while (flag) {
                    cnt++;
                }
                System.out.println("Thread1 finished\n");
            }
        ).start();
        new Thread(()-> {
                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();
    }
}

위 코드를 봅시다. 두 개의 스레드를 여는데 하나의 스래드를 flag라 true인 동안 루프로 cnt를 증가시키고, 다른 스레드는 100ms 동안 sleep 하였다가 flag를 false로 만듭니다.

단순하게 생각하면 두 번째 스레드가 100ms만큼 sleep하는 동안 첫 번째 스레드가 cnt를 증가시킨 후, flag가 false가 되어 루프가 중단될 것이라 생각 할 수 있습니다.

하지만 실제로 위 코드를 실행해보면 위와 같이 두 번째 스레드의 flag to false만 출력이 되고 무한 루프에 빠진 것을 확인 할 수 있습니다.

앞서 설명했던 각 스레드가 각자의 CPU Cache에 값을 활용해서 생긴 문제입니다. 첫 번째 스레드는 자신의 Cache에 복사해놓은 flag의 값만 죽어라 확인하고 있는 것입니다.

volatile boolean flag = true;

해결 방법은 위와 같이 flag에 volatile 키워드를 붙이는 것입니다. volatile 키워드를 붙인다는 것은 변수를 CPU Cache가 아니라 메인 메모리에 저장하겠다는 명시입니다.

volatile를 붙이고 실행하면 첫 번째 스레드가 잘 종료되어 Thread1 finished가 출력되는 것을 확인할 수 있습니다.

참고

https://www.youtube.com/watch?v=4Sk9dzXgKwo&list=PLTC3gIv9IzFLblGSX7yf_4p9VeUqAr_9q&index=3

profile
응애 개발자입니다.

0개의 댓글