Java에서 변수 값을 설정하는 작업은 long 및 double 유형 변수를 제외하고는 원자적 작업이라는 것을 알고 있습니다. 즉, 변수 값의 간단한 읽기 및 쓰기 작업을 동기화할 필요가 없습니다.
JVM 1.2 이전에는 Java의 메모리 모델 구현이 항상 주 메모리에서 변수를 읽었으므로 특별한 주의가 필요하지 않았습니다. JVM의 성숙도와 최적화로 인해 멀티스레드 환경에서는 휘발성 키워드의 사용이 매우 중요해졌습니다. 현재 Java 메모리 모델에서 스레드는 주 메모리에서 직접 읽고 쓰는 대신 로컬 메모리(예: 머신 레지스터)에 변수를 저장할 수 있습니다. 이로 인해 한 스레드가 주 메모리의 변수 값을 수정하는 반면 다른 스레드는 레지스터에 있는 변수 값의 복사본을 계속 사용하여 데이터 불일치가 발생할 수 있습니다. 이 문제를 해결하려면 이 프로그램에서처럼 변수를 휘발성(불안정)으로 선언하기만 하면 됩니다. 이는 이 변수가 불안정하며 읽을 때마다 주 메모리에 저장된다는 것을 JVM에 나타냅니다. 일반적으로 말하면
따라서 멀티 태스킹 환경에서는 태스크 간에 공유되는 플래그를 휘발성으로 수정해야 합니다.
Volatile에 의해 수정된 멤버 변수가 스레드에 의해 액세스될 때마다 멤버 변수의 값은 공유 메모리에서 강제로 다시 읽혀집니다. 또한 멤버 변수가 변경되면 스레드는 변경된 값을 공유 메모리에 다시 써야 합니다. 이러한 방식으로 언제든지 두 개의 서로 다른 스레드가 항상 동일한 멤버 변수 값을 볼 수 있습니다.
Java 언어 사양은 다음과 같이 명시합니다. 최적의 속도를 위해 스레드는 공유 멤버 변수의 개인 복사본을 저장하고 스레드가 동기화된 코드 블록에 들어가거나 나갈 때만 이를 공유 멤버 변수의 원래 값과 비교할 수 있습니다.
이런 방식으로 여러 스레드가 동시에 개체와 상호 작용할 때 스레드가 공유 멤버 변수의 변경 사항을 적시에 얻을 수 있도록 주의를 기울여야 합니다.
휘발성 키워드는 VM에 메시지를 표시합니다. 이 멤버 변수의 개인 복사본을 저장할 수 없지만 공유 멤버 변수와 직접 상호 작용해야 합니다.
사용법 제안: 둘 이상의 스레드에서 액세스하는 멤버 변수에 휘발성을 사용하십시오. 접근하려는 변수가 이미 동기화된 코드 블록에 있거나 상수인 경우에는 사용할 필요가 없습니다.
휘발성을 사용하면 VM에서 필요한 코드 최적화가 차단되므로 효율성이 떨어지므로 이 키워드는 필요한 경우에만 사용해야 합니다.
가상 머신 구현에서 int 및 char과 같은 기본 유형의 길이는 한 단어입니다. 그리고 long과 double은 길이가 두 단어를 차지합니다. 일부 가상 머신 구현에서는 두 단어 길이가 두 원자 단일 단어 길이로 처리 될 수 있습니다 .
long 및 double이 휘발성으로 수정되지 않은 경우 여러 스레드가 변수에 액세스하면 긴 작업의 전반적인 비원자성으로 인해 결과가 혼란스러워집니다.
예: int, 한 스레드는 4를 쓰고 다른 스레드는 5를 씁니다. 최종 값은 4 또는 5여야 합니다. 그리고 long 유형은 지저분한 값일 수 있습니다.