2011-02-03 6 views
22

우리는 다른 스레드가 액세스하는 동일한 변수 사본을 유지하기 위해 우리 프로젝트 중 하나에서 volatile을 사용합니다. 제 질문은 volatilestatic을 사용하는 것이 괜찮은지 여부입니다. 컴파일러는 오류를주지는 않지만 둘 다 사용하는 이유를 이해하지 못합니다.Java에서 "휘발성"은 무엇을 의미합니까?

답변

17

메모리 모델 사양을 읽지 않아도 되겠지만 http://jeremymanson.blogspot.com/2008/11/what-volatile-means-in-java.html을 읽는 것이 좋습니다. JMM 작성자 중 한 명이 작성 했으므로 질문에 대답해야합니다. happens-before 절의 관점에서 메모리 읽기 및 쓰기를 생각하는 것도 도움이됩니다. Java 5 용 JMM은 발생시 이전의 의미를 volatile에 추가합니다.

특히, 한 스레드에서 휘발성 변수를 읽으면 다른 스레드의 해당 휘발성 변수에 대한 쓰기를 포함하여 모든 쓰기가 해당 스레드에 표시됩니다. 잠깐 시간이 있다면, Google 기술 토론에서 주제를 더 자세히 설명합니다 : https://code.google.com/edu/languages/#_java_memmodel.

staticvolatile을 사용할 수 있습니다. 그들은 다른 일을합니다.

+0

의 업데이트 된 값을 얻는 것이 scenarion에서

: 당신이 모든이 모든 변수에 기록을 의미합니까, 또는 모두가 하나 개 휘발성 변수에 기록? – fredoverflow

+0

나는 그것이 읽히는 휘발성 변수에 마지막으로 쓰기 전에 모든 변수에 대한 모든 쓰기라고 생각한다. – ide

+3

"필드가 휘발성으로 선언되면 컴파일러와 런타임은이 변수가 공유되고 해당 작업이 다른 메모리 작업과 다시 정렬되어서는 안된다는 사실을 알게됩니다. 휘발성 변수는 숨겨진 레지스터 또는 캐시에 캐시되지 않습니다 휘발성 변수를 읽으면 항상 모든 스레드가 가장 최근에 쓰는 것을 반환합니다. " Bloch, Joshua; 게츠, 브라이언; Peierls, Tim; Bowbeer, Joseph; 홈즈, 데이비드; Lea, Doug (2006-05-09). Java Concurrency in Practice (Kindle Locations 1194-1197). Pearson Education (미국). 킨들 에디션. – James

7

volatile은 런타임에 변수가 변경되고 컴파일러가 어떤 이유로 든 값을 캐시해서는 안된다는 것을 의미합니다.

이것은 스레드간에 변수를 공유 할 때만 실제로 문제입니다. 스레드가 부실 데이터로 작업하는 것을 원하지 않으므로 컴파일러는 변수 참조 volatile의 값을 캐시해서는 안됩니다.

+0

"_inline its value_"포옹? – curiousguy

10

휘발성 변수는 C와 비슷한 일반적인 의미를 갖습니다. Java 메모리 모델 (IDE의 답변에있는 훌륭한 링크 참조)은 스레드가 비표준 변수로 동시에 다른 값을 "볼"수있게합니다 -휘발성 물질.

스레드 A : :

n = 1; 
// wait... 
n = 2; 

스레드 B와 C : 예를 들어

while (true) { 
    System.out.println(name + ": " + n); 
} 

이 출력은 B와 C 사이에 엄격 대체 보장되지하고 있습니다 (일어날 수있다 B와 C의 "전환 (changeover)"을 여기 보여 주려고합니다.) :

C: 1 
B: 1 
C: 2 
B: 1 
C: 2 
B: 2 

이것은 완전히 별개입니다. 자물쇠는 println에 의하여 가지고 갔다; 스레드 B는 입니다.은 C가 2라는 것을 알게 된 후에도 n을 1로 보았습니다. 충분히 이해할 수있는 척도가 될 수없는 많은 이유가 있습니다. 속도와 보안에 관련된 많은 것들이 있습니다 .

변동성이있는 경우 (즉시 무시할 println의 잠금을 제외하고) B와 C가 동시에 B의 새로운 값을 즉시 볼 수 있음을 보증합니다 보냈습니다.

volatilestatic과 다른 작업에 영향을주기 때문에 사용할 수 있습니다. volatile은 해당 변수를 사용하기 전에 해당 변수를 사용하는 모든 스레드에 변수를 "복제"하도록 변경하는 반면 static은 해당 변수를 사용하는 모든 클래스에 하나의 변수를 공유합니다.(Thread은 모두 class으로 구현되기 때문에 Java에서 스레딩을 처음 사용하는 사람들은 다소 혼란 스러울 수 있습니다.

2

휘발성은 여러 스레드가 동일한 변수에 액세스해야하는 여러 상황에서 사용됩니다. 다중 스레드/동시 프로그래밍을 수행하지 않는 많은 사람들이 이에 노출되지 않습니다. 휘발성 (Volatile)은 변수가 항상 주 메모리에서 읽히고 캐시/레지스터 버전에서는 읽히지 않도록합니다. 휘발성 자체는 잠금이 아닙니다. 모든 스레드가 작성되는 즉시 변경 사항을 볼 수 있다고해서 원자 적 방법으로 비교하고 바꿀 수 있다는 의미는 아닙니다. 그러나이 기능은 compare-and-swap과 같은 다른 기능과 함께 사용하여 "무거운"Java 대기 응답 구문을 사용하지 않고도 스레드로부터 안전한 데이터 구조를 작성할 수 있습니다.

Thread1이 실행될 때 두 개의 스레드 (Thread1하고 Thread2가) 값 1

과 같은 변수 'mObject'에 액세스하는 경우 http://www.quora.com/Threading-in-Java/What-is-the-purpose-of-the-volatile-keyword-in-java

1

이 시나리오를 고려 링크에 더 많은 정보를 얻을 수 있습니다, 그것을 다른 스레드가 'mObject'변수를 수정한다고 기대하지 않습니다. 이 시나리오에서 Thread1은 변수 'mObject'를 값 1로 캐시합니다.

그리고 Thread2가 'mObject'값을 2로 수정하면 Thread1은 캐싱을 수행 한 이후 mObject 값을 1로 참조합니다. 이 캐싱을 피하려면 다음과 같이 변수를 선언해야합니다.

private volatile int mObject; Thread1이 mObject 두 번째 단락에 관한

관련 문제