때로는 컴파일러와 프로세서의 최적화로 인해 런타임이 상상했던 것과 다릅니다. 이러한 이유로 Java는 컴파일러 및 프로세서에 약간의 제한 사항을 부과했습니다. JMM (Java Memory Model)은 코드를 작성할 때 많은 기본 세부 사항을 고려할 필요가 없도록이를 추상화하고 "JMM 규칙을 따라 프로그램을 작성하는 한 실행 결과가 정확해야합니다."
JMM의 추상 구조
Java에서는 모든 인스턴스와 정적 변수가 힙 메모리에 저장되며 스레드간에 공유 할 수 있으며이 부분을 공유 변수 라고도합니다. 로컬 변수, 메소드 정의 매개 변수 및 예외 처리 매개 변수가 스택에 있으며 스택 메모리는 스레드간에 공유되지 않습니다.
그러나 컴파일러 및 프로세서의 최적화로 인해 공유 변수에 대한 가시성 문제가 발생합니다. 예를 들어, 다중 프로세서에서는 다른 프로세서에서 스레드를 실행할 수 있으며 프로세서간에 일치하지 않는 캐시는 공유 변수의 가시성 문제를 유발합니다 . 두 스레드는 동일한 변수의 다른 값을 볼 수 있습니다.
JMM은 이러한 하드웨어로 만든 최적화를 각 스레드에 로컬 메모리를 가지고 있다고 추상화합니다. 공유 변수를 읽고 쓸 필요가 있으면 기본 메모리에서 로컬 메모리로 사본을 복사하십시오. 공유 변수를 쓸 때 먼저 로컬 메모리에 쓰고 앞으로도 메인 메모리로 새로 고치십시오. 공유 변수를 다시 읽으면 로컬 메모리에서만 읽습니다.
이런 식으로 스레드 간의 통신에는 두 단계가 필요합니다.
쓰레기 쓰기 : 로컬 메모리를 새로 고치고 스레드를 읽으십시오 : 메인 메모리에서 업데이트 된 값을 읽으십시오.
이런 식으로, 글쓰기와 독서 사이에는 지연이 있습니다. 현지 메모리는 언제 메인 메모리로 새로 고침됩니까? 이로 인해 가시성 문제가 발생하며 다른 스레드는 다른 공유 변수를 볼 수 있습니다.
앞서 발생합니다
말 그대로 "이 전에 일어나기 전에"라는 의미가 있습니다. 이것은 Java가 프로그램 실행 순서에 따라 공식화되는 규칙이며 동기화를 따라야합니다. 이런 식으로 프로그래머는 올바른 동기 프로그램 만 작성하면되며 실행 결과가 잘못되지 않도록하기 전에 발생합니다.
A가 발생하면 A가 A가 B 전에 실행되었음을 의미 할뿐만 아니라 A의 실행 결과가 B로 표시되어 가시성을 보장합니다.
A 이전에 A가 발생하면 A가 B보다 먼저 실행될 필요가 없습니다. AB가 번갈아 가며 실행 결과가 여전히 올바른 경우 컴파일러와 프로세서가 재주문을 최적화 할 수 있습니다. 따라서 프로그램 결과가 올바른 한 컴파일러와 프로세서가 어떻게 최적화하고 재정렬하는지에 문제가 없으며 모두 좋습니다.
앞서는 규칙이 발생합니다
프로그램 시퀀스 규칙 : 스레드에서 이전 작업 후 조작 잠금 규칙이 발생합니다. 동일한 잠금의 경우 잠금 해제가 발생하고 휘발성 도메인 규칙을 잠금 해제합니다. 작업의 트랜지 시크 : A가 발생하여 발생하는 경우에 발생하면 C가 발생합니다. C START () 규칙에 따라 A가 발생합니다. STREAR A가 실행하면 residb.Start ()가 실행되면 threadB.Start ()가 실행되기 전에 실행됩니다.
다음 예제는 앞서서 일어나는 것을 이해하는 데 도움이됩니다
이중 PI = 3.14; // adouble r = 1.0; // bdouble 영역 = pi * r * r; //기음
관계는 다음과 같은 관계가 있습니다. 규칙 1과 2는 프로그램 순서 규칙이며 규칙 3은 전이 규칙에서 파생됩니다.
ca가 발생하기 전에 BB가 발생하기 전에 발생하기 전에 c
C는 A와 B에 의존하지만 A 또는 B는 그것에 의존하지 않습니다. 따라서 A와 B가 재정렬 되더라도 실행 결과는 변경되지 않습니다. 이 재주문에서 JMM이 실행 중입니다.
다음 두 가지 실행 시퀀스가 정확합니다.
위는 Java 메모리 모델 JMM 학습에 대해 우리가 편집 한 모든 컨텐츠입니다. 더 많은 질문을 보려면 아래 메시지를 남겨 두십시오. wulin.com을 지원 해주셔서 감사합니다.