[Thread] volatile
volatile
volatile을 통해 캐시와 메모리 간의 불일치를 해소할 수 있다.
성능 향상을 위해 변수의 값을 core의 cache에 저장해 놓고 작업을 하게 된다. 멀티 코어 프로세서에서는 위처럼 코어마다 별도의 캐시를 가지고 있다. 코어는 메모리에서 읽어온 값을 캐시에 저장하고 캐시에서 값을 읽어서 작업을 한다. 같은 값을 읽어올 때는 먼저 캐시에 있는지 확인하고 없을 때만 메모리에서 읽어온다.
따라서 도중에 메모리에 저장된 변수의 값이 변경되었는데도 캐시에 저장된 값이 갱신되지 않아서 메모리에 저장된 값과 캐시에 저장된 값이 다른 경우가 발생한다.
변수에 앞에 volatile을 붙이면 코어가 변수의 값을 일거올 때 캐시가 아니라 메모리에서 읽어오기 때문에 캐시와 메모리 간의 값의 불일치가 해소된다.
volatile boolean suspended = false;
volatile boolean stopped = false;
변수에 volatile을 붙이는 대신 synchronized 블록을 사용해도 같은 효과를 얻을 수 있다. 스레드가 synchronized 블록으로 드나들 때 캐시와 메모리 간의 동기화가 이루어지기 때문이다.
volatile로 원자화
JVM은 데이터를 4 byte 단위로 처리하기 때문에 int와 int보다 작은 타입들은 한 번에 읽거나 쓰는 것이 가능하다. 따라서 작업의 중간에 다른 스레드가 끼어들 틈이 없다.
하지만 8 byte인 long과 double은 하나의 명령어로 값을 읽거나 쓸 수 없기 때문에 다른 스레드가 끼어들 여지가 있다. 다른 스레드가 끼어들지 못하게 하기 위해 변수를 선언할 때 volatile을 붙일 수 있다.
volatile long sharedVal; // long 타입의 변수를 원자화
volatile double sharedVal; // double 타입의 변수를 원자화
synchronized 블록을 통해서도 일종의 원자화를 할 수 있다. 하지만 volatile로는 동기화를 할 수 없다.