프로그래머가 동기화에 사용 된 변수에 volatile
키워드를 추가하는 것을 잊어 버린 경우 캐시 시점 (MESI 프로토콜)에서 어떤 일이 발생하는지 알고 싶습니다.휘발성 변수가없는 깨진 동기화
다음 코드 스 니펫은 일부 반복 후에는 단순히 멈 춥니 다. 두 스레드 중 하나 (THREAD 0을 가정 해 봅시다)가 current
에 대한 업데이트를 getNext()에 의해 THREAD 1에 의해 수행 된 것을 보지 못하기 때문에 그것이 영원히 계속 반복되는 것을 알고 있습니다.
그러나 나는 왜 그런지 이해하지 못합니다. THREAD 0은 current
에서 루핑되고 어느 시점에서 캐시 라인이 THREAD 1 (캐시 라인이 수정 됨 상태로 전환 됨)에 의해 업데이트되고 메모리 캐시에서 로컬 캐시에서 패치를 가져 오는 "읽기"메시지를 표시해야합니다. 변수 current
에 volatile
수정자를 추가하면 모든 것이 잘 작동합니다.
THREAD 0의 실행이 계속되는 것을 방지하는 어떤 현상이 발생합니까?
참조 : Memory Barriers: a Hardware View for Software Hackers
public class Volatile {
public static final int THREAD_0 = 0;
public static final int THREAD_1 = 1;
public static int current;
public static int counter = 0;
public static void main(String[] args) {
current = 0;
/** Thread 0 **/
Thread thread0 = new Thread(() -> {
while(true) { /** THREAD_0 */
while (current != THREAD_0);
counter++;
System.out.println("Thread0:" + counter);
current = getNext(THREAD_0);
}
});
/** Thread 1 **/
Thread thread1 = new Thread(() -> {
while(true) { /** THREAD_1 */
while (current != THREAD_1);
counter++;
System.out.println("Thread1:" + counter);
current = getNext(THREAD_1);
}
});
thread0.start();
thread1.start();
}
public static int getNext(int threadId) {
return threadId == THREAD_0 ? THREAD_1 : THREAD_0;
}
}
,이 문제는 JIT 컴파일러와 관련이 있습니다. 해석 모드 (-Xint)에서만 프로그램을 시작하면 컴파일 된 모드 (-Xcomp)에서는 작동하지 않지만 영원히 작동합니다. 이 답변을 주셔서 감사합니다! –