Java adv1 - 메모리 가시성 ( volatile )

dev1·2024년 11월 27일

volatile ==> 캐시메모리가아니라 메인메모리에 있는거로 참조하도록 변경

=============================================

package thread.volatile1;

import static util.MyLogger.log;
import static util.ThreadUtils.sleep;

public class VolatileFlagMain {

    public static void main(String[] args) {
        MyTask task = new MyTask();
        Thread t = new Thread(task, "work");
        log("runFlag = " + task.runFlag);
        t.start();

        sleep(1000);
        log("runFlag 변경 시도");
        task.runFlag = false;
        log("runFlag = " + task.runFlag);
        log("main 종료");

    }

    static class MyTask implements Runnable{

        boolean runFlag = true;

        @Override
        public void run() {
            log("task 시작");
            while ( runFlag ) {

            }
            log("task 종료");
        }

    }
}

===> task 종료가 나오지않음 ( 스레드 종료 ㄴㄴ. == > while 문을 계속 ... ).

왜 이러한 방식으로 작동 ?

===> 캐시메모리때문에

그럼 캐시메모리 ?

//// 메인메모리랑 CPU 의 거리? 때문에 값을 읽어들이고 처리하는게 오래걸림 ..

그래서, 정보를 처리하는 CPU 근처에 메모리에 해당하는 값들을 배치... => 캐시메모리 공간에 저장

즉, 메모리에 저장되어져있는 runFlag = true // 를 캐시메모리에 복사해서 저장

==================

runFlag 변경시도 : ==> main 스레드에서 변경 /// ==> main 스레드에 해당하는 cpu 에 있는 캐시메모리에 값 ( runFlag ) 를 변경

반면에, main 스레드가 아닌 다른 스레드인 t 스레드에 해당하는 cpu 에 있는 캐시메모리 값 ( runFlag ) 는 변경이 되지않았음 ( 아직 true )

그래서, 계속해서 while 문을 돌고있는 상태 ...

그러면, 결국 캐시메모리때문에 문제가 생긴것이니...

직접 메인메모리에있는 값 ( runFlag ) 를 변경해주면됨

==> 그럼이제 메인메모리를 참조하도록 할려면 어떻게해야함 ? ==> volatile 키워드 사용 ㄱㄱ

package thread.volatile1;

import static util.MyLogger.log;
import static util.ThreadUtils.sleep;

public class VolatileFlagMain {

    public static void main(String[] args) {
        MyTask task = new MyTask();
        Thread t = new Thread(task, "work");
        log("runFlag = " + task.runFlag);
        t.start();

        sleep(1000);
        log("runFlag 변경 시도");
        task.runFlag = false;
        log("runFlag = " + task.runFlag);
        log("main 종료");

    }

    static class MyTask implements Runnable{

        volatile boolean runFlag = true;

        @Override
        public void run() {
            log("task 시작");
            while ( runFlag ) {

            }
            log("task 종료");
        }

    }
}

==> volatile boolean runFlag = true;

/// runFlag 값은 메인메모리에있는거로 참조하셈 ( 캐시메모리 말고 )

0개의 댓글