본문 바로가기
Language/Java

[Java] 쓰레드 7 - volatile

by 계범 2022. 3. 14.

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의 정석' 책

댓글