
메모리는 메인 메모리가 있고, CPU마다 캐시 메모리가 있다.
값이 저장되는 곳이 두 곳이 있다는 이야기.
두 곳에서 관리되고 있다면 그 사이에서 뭔가 빈틈이 있지 않을까?
빈틈에서 벌어지는 메모리 가시성 문제
그리고 그 해결책인 volatile에 대해 알아보자.

boolean runningFlag = false;
runningFlag = true; // ** 데이터 변경 **
데이터 변경가 변경될 때에는
먼저 메인 메모리가 아닌 캐시 메모리에서 관리되는 데이터가 변경된다.
캐시 메모리의 데이터가 변경되면, 그 이후 메인 메모리의 데이터가 변경되고
변경된 메인 메모리를 바탕으로 다른 CPU들의 캐시 메모리가 변경된다.

스레드는 데이터에 접근할 때, 메인 메모리가 아닌 캐시 메모리에 접근한다.
메인 메모리에 접근하는 것은 더 복잡하기 때문에,
빠른 성능을 위해 캐시 메모리에 접근하는 것이다.
데이터가 변경되는 과정은 위처럼 캐시 메모리부터 메인 메모리,
다른 CPU의 캐시 메모리까지 순차적으로 이루어지기 때문에
스레드가 데이터에 접근할 때 아직 변경 중인 상태의 데이터에 접근하게 될 수 있다.
이 경우 변경되지 않은 데이터를 반환받게 된다.

데이터 변경 이후 변경된 데이터가 다른 메모리에 기록되는 것은
보통 컨텍스트 스위칭 과정에서 발생한다.
그렇다면 컨텍스트 스위칭이 일어날 때까지 기다렸다가 데이터에 접근해야 하는가?
당연히 그렇지 않을 것이다.
데이터가 빠르게 메모리에 기록될 수 있도록 하기 위해서
자바에서는 volatile이라는 키워드를 지원한다.
volatile runningFlag = false;
runningFlag = true;
volatile로 선언한 변수는 변경 시 메인 메모리에 즉시 반영된다.
따라서 여러 스레드가 해당 데이터에 접근해도
변경되지 않은 데이터를 반환받을 일이 없다.

멀티 스레드에 돌입하면서 동기화 문제를 마주하게 된다.
유의해야할 것은 volatile은 메모리 가시성,
즉 데이터를 읽는 시점에서의 동기화 문제를 말하는 것이다.
동시에 데이터를 변경하는 동시성 문제를 해결하는 근본적인 해결책은 될 수 없다.
멀티 스레드 환경에서는 volatile 변수를 고려해보자.