JSR133 중volatile 키워드 이해

The original semantics for volatile guaranteed only that reads and writes of volatile fields would be made directly to main memory, instead of to registers or the local processor cache, and that actions on volatile variables on behalf of a thread are performed in the order that the thread requested. In other words, this means that the old memory model made promises only about the visibility of the variable being read or written, and no promises about the visibility of writes to other variables. While this was easier to implement efficiently, it turned out to be less useful than initially thought.
While reads and writes of volatile variables could not be reordered with reads and writes of other volatile variables, they could still be reordered with reads and writes of nonvolatile variables. In Part 1 , you learned how the code in Listing 1 was not sufficient (under the old memory model) to guarantee that the correct value for configOptions and all the variables reachable indirectly through configOptions (such as the elements of the Map ) would be visible to thread B, because the initialization of configOptions could have been reordered with the initialization of the volatile initialized variable.
Map configOptions;
char[] configText;
volatile boolean initialized = false;
//In Thread A
configOptions = new HashMap();
configText = readConfigFile(fileName);
processConfigOptions(configText, configOptions);
initialized = true;
//In Thread B
while (!initialized)
sleep();
//use configOptions
Unfortunately, this situation is a common use case for volatile -- using a volatile field as a "guard"to indicate that a set of shared variables had been initialized. The JSR 133 Expert Group decided that it would be more sensible for volatile reads and writes not to be reorderable with any other memory operations -- to support precisely this and other similar use cases. Under the new memory model, when thread A writes to a volatile variable V, and thread B reads from V, any variable values that were visible to A at the time that V was written are guaranteed now to be visible to B. The result is a more useful semantics of volatile , at the cost of a somewhat higher performance penalty for accessing volatile fields.
volatile의 의미:
1. volatil e역에 대한 읽기와 쓰기가 메인 메모리에서 직접 진행되고 루트의 로컬 메모리에 캐시되지 않도록 합니다.
2. 이전 JMM에서 volatil e역의 작업과 nonvolatil e역의 작업 사이를 다시 정렬할 수 있습니다.그러나 JSR133 이후volatile 작업과 다른 메모리 작업 사이에는 재배열을 허용하지 않는다.
3. 새로운 JMM에서 스레드 A가volatile 변수 V를 쓴 다음에 스레드 B가 V를 읽을 때 스레드 A에 대한 모든 변수 값을 B에 표시합니다
세 번째는 이상해요. 약간 Synchronized의 작용인 것 같아요.루틴 A가volatile 변수를 쓸 때 로컬 캐시에 있는non-volatile 변수를 메모리에 새로 고침하고,volatile 변수를 읽을 때 로컬 캐시에 있는non-volatile 변수를 업데이트합니까?그렇지 않으면 라인 B가 어떻게 그런 nonvolatile 변수를 볼 수 있겠는가?
이 문제에 대해 몇 가지 자료를 조회하였는데'volatile 필드의 읽기와 쓰기는 모니터에 들어오고 종료하는 것과 비슷한 메모리 일치성 효과가 있다'(http://blog.csdn.net/lovingprince/archive/2010/04/04/5450246.aspx)
volatile 변수의 읽기와 쓰기에happens-before의 편차 관계가 있습니다
A write to a volatile fieldhappens-before every subsequent read of that same volatile. 이 점은 의문이 없다.
Because the write of the volatile variable initialized happens after the initialization of configOptions , the use of configOptions happens after the read of initialized , and the read of initialized happens after the write to initialized , you can conclude that the initialization of configOptions by thread A happens before the use of configOptions by thread B. Therefore, configOptions and the variables reachable through it will be visible to thread B.
새 JMM에서volatile을 사용하면 위의 코드가 합리적인지 확인할 수 있습니다.다음 "<"는 happens-before의 뜻입니다.
1. "스레드 A에서 configOptions 초기화"<"스레드 A에서 initialized 변수 쓰기"
2. "스레드 B에서 initialized 변수 읽기"<"스레드 B에서 configOptions 사용"
3. “write to volatile field” < “subsequent read of that same volatile”
또한 action1 그래서 우리는'스레드 A에서 configOptions 초기화'<'스레드 B에서 configOptions 사용'을 얻어낼 수 있다.
즉volatile 변수를 사용한 후non-volatile 변수의 조작 사이에도happens-before 관계가 생겼다는 것이다.

좋은 웹페이지 즐겨찾기