volatile
코어는 메모리에서 읽어온 값을 캐시에 저장하고 캐시에서 값을 읽어서 작업한다.
다시 같은 값을 읽어올 때는 먼저 캐시에 있는지 확인하고 없을 때만 메모리에서 읽어온다.
그러다보니 도중에 메모리에 저장된 변수의 값이 변경되었는데도 캐시에 저장된 값이 갱신되지 않아서 메모리에 저장된 값이 다른 경우가 발생한다. 그럴 때 변수 앞에 volatile을 붙이면, 코어가 변수의 값을 읽어올 때 캐시가 아닌 메모리에서 읽어온다.
boolean suspended = false;
// volatile
volatile boolean suspended = false;
volatile을 붙이는 대신에 synchronized블럭을 사용해도 같은 효과를 얻을 수 있다.
쓰레드가 블럭에 들어갈 때와 나올 때, 캐시와 메모리간의 동기화가 이루어지기 때문에 값의 불일치가 해소된다.
volatile로 long과 double을 원자화
JVM은 데이터를 4Byte(=32bit)단위로 처리하기 때문에, int와 int보다 작은 타입들은 한번에 읽거나 쓰는 것이 가능하다.
즉, 하나의 명령어로 읽거나 쓰는 것이 가능하기 때문에, 작업의 중간에 다른 쓰레드가 끼어들 일이 없다.
하지만 long과 double은 하나의 명령어로 값을 읽거나 쓸 수 없는데, synchronized블럭으로 감싸거나 volatile을 변수 앞에 붙이는 것으로 해결할 수 있다.
volatile을 붙이면 변수에 대한 읽거나 쓰기가 원자화된다.
동기화하는 것은 아니니 주의하자!
참조
'Java의 정석' 책
'Language > Java' 카테고리의 다른 글
[Java] 람다식(Lambda expression)과 함수형 인터페이스(Functional Interface) (0) | 2022.03.16 |
---|---|
[Java] 쓰레드 8 - fork & join 프레임 워크 (0) | 2022.03.14 |
[Java] 쓰레드 6 - 쓰레드 동기화(synchronized , Lock, Condition) (0) | 2022.03.14 |
[Java] 쓰레드 5 - 쓰레드의 실행제어(sleep, interrupt, join, yield) (0) | 2022.03.14 |
[Java] 쓰레드 4 - 데몬 쓰레드(daemon thread) (2) | 2022.03.14 |
댓글