Volatile

0

JAVA

목록 보기
12/18

volatile이 선언되 변수는 즉시 메인 메모리에 저장할 것을 의미합니다.
모든 volatile 변수는 컴퓨터의 메인 메모리로부터 읽기하고, volatile 변수에 대한 쓰기 작업은 CPU 캐시가 아닌 메인 메모리에 이루어집니다.

가시성 보장

멀티스레드 환경에서의 non-volatile 변수에 대한 작업은 성능상의 이유로 CPU 캐시를 사용합니다.
이때, 둘 이상의 CPU가 탑재된 컴퓨터에서 어플리케이션을 실행한다면, 각 스레드는 변수를 각 CPU의 캐시로 복사형 읽습니다.


(출처 : http://tutorials.jenkov.com/java-concurrency/volatile.html)

이러한 환경에서 non-volatile 변수는 JVM이 메인 메모리로부터 CPU 캐시로 변수를 읽어들이거나 CPU 캐시로부터 메인 메모리에 데이터를 쓸 때 원자성에 대한 보장을 할 수 없습니다.
아래는 위와 같은 상황에서의 문제발생 예시 입니다.

public class Example{
	public int cnt = 0;
}

조건 1 : Thread1은 cnt 변수를 증가시킨다.
조건 2 : Thread1과 Thread2는 때에 따라서 cnt 변수를 읽는다


위와 같은 예시에서 cnt 변수에 volatile 키워드가 없다면, cnt 변수가 언제 CPU 캐시에서 메인 메모리로 쓰일지 알 수 없습니다.
즉, CPU 캐시의 cnt변수와 메인 메모리의 cnt 변수가 다른 값을 가질 수 있는 상태인 것 입니다.


(출처 : http://tutorials.jenkov.com/java-concurrency/volatile.html)

이러한 상황을 가시성 문제라고 합니다.
스레드가 변경한 값이 메인 메모리에 저장되지 않아서 다른 스레드가 이 값을 볼 수는 상황이라는 의미입니다.

이러한 가시성 문제를 해결하기 위해 사용하는 것이 바로 volatile입니다.
만약 cnt 변수에 volatile 키워드를 선언한다면 이 변수에 대한 쓰기 작업은 즉시 메인 메모리에 이루어 질 것이고, 읽기 작업 또한 메인 메모리로부터 다이렉트로 이루어지게 됩니다.


volatile은 완벽한 해결 방법이 될까?

스레드가 volatile 변수의 초기 값을 필요로 할 때, 그리고 volatile 변수의 새 값이 이 초기값을 근거로 할 때 volatile 선언은 더 이상 가시성을 보장하지 못합니다.
왜냐하면 volatile 변수를 읽고, 새 값을 쓰는 사이의 짧은 순간에 경합이 발생할 수 있으며 이로인해 다수의 스레드가 volatile 변수의 값을 똑같이 읽고, 새 값을 생성하여 이를 메인 메모리로 저장하는 동안 서로의 값을 덮어 쓸 수 있기 때문입니다.
예시로 여러 스레드가 동시에 cnt 값을 증가시키는 상황이 volatile 변수가 불완전해지는 상황이라고 할 수 있습니다.

profile
컴퓨터공학과 + 실무 = 4 + N = 모르는거 ∞ ...

0개의 댓글