1. volatile, 메모리 가시성1

package thread.control.volatile1;

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

public class VolatileFlagMain {

    public static void main(String[] args) {

        MyTask myTask = new MyTask();
        Thread t = new Thread(myTask, "work");

        log("runFlag = " + myTask.runFlag);

        t.start();
        sleep(1000);
        log("runFlag를 false로 변경 시도");
        myTask.runFlag = false;
        log("runFlag = " + myTask.runFlag);
        log("main 종료");
    }

    static class MyTask implements Runnable {

        boolean runFlag = true;
//        volatile boolean runFlag = true; // 캐시 메모리가 아닌 메인 메모리에 직접 접근 (읽을 때도 항상 메인 메모리 활용)

        @Override
        public void run() {

            log("task 시작");

            while(runFlag){

            }

            log("task 종료");
        }
    }
}

메모리

image.png

기대 결과

09:08:22.458 [     main] runFlag = true
09:08:22.461 [     work] task 시작
09:08:23.470 [     main] runFlag를 false로 변경 시도
09:08:23.470 [     work] task 종료
09:08:23.470 [     main] runFlag = false
09:08:23.471 [     main] main 종료

실행 결과

09:07:40.860 [     main] runFlag = true
09:07:40.863 [     work] task 시작
09:07:41.873 [     main] runFlag를 false로 변경 시도
09:07:41.873 [     main] runFlag = false
09:07:41.873 [     main] main 종료

분명 runFlagfalse로 변경했지만 while을 탈출하지 못한다. 왜일까?

2. volatile, 메모리 가시성2

메모리 가시성 문제

일반적으로 생각하는 메모리 접근 방식

image.png