> Java > java지도 시간 > 본문

JAVA의 JVM 재정렬에 대한 자세한 소개

高洛峰
풀어 주다: 2017-01-23 10:20:57
원래의
1425명이 탐색했습니다.

동시 프로그램에서 프로그래머는 서로 다른 프로세스나 스레드 간의 데이터 동기화에 특별한 주의를 기울일 것입니다. 특히 여러 스레드가 동시에 동일한 변수를 수정하는 경우 데이터가 올바르게 수정되도록 안정적인 동기화 또는 기타 조치를 취해야 합니다. 여기서 중요한 원칙은 명령이 실행되는 순서에 대해 가정하지 않는다는 것입니다. 서로 다른 스레드 간의 명령이 실행되는 순서를 예측할 수 없습니다.

그러나 단일 스레드 프로그램에서는 일반적으로 명령이 순차적으로 실행된다고 가정하기 쉽습니다. 그렇지 않으면 프로그램에 어떤 끔찍한 변화가 일어날지 상상할 수 있습니다. 이상적인 모델은 다양한 명령이 실행되는 순서가 고유하고 순서가 있다는 것입니다. 이 순서는 프로세서나 기타 요인에 관계없이 코드에 기록되는 순서입니다. von Neumann 시스템을 기반으로 한 모델입니다. 물론 이 가정은 그 자체로 타당하며 실제로는 비정상적으로 거의 발생하지 않지만 실제로는 너무 비효율적이기 때문에 현대의 다중 프로세서 아키텍처에서는 이 모델을 채택하지 않습니다. 컴파일 최적화 및 CPU 파이프라인에서는 거의 모두 명령 재정렬과 관련됩니다.

컴파일 시간 재정렬

일반적인 컴파일 시간 재정렬은 명령어 순서를 조정하여 프로그램 의미를 변경하지 않고 레지스터 읽기 및 저장 횟수를 최대한 줄이고, 레지스터의 저장된 값을 사용하여 완전히 복제합니다.

첫 번째 명령어가 값을 계산하여 변수 A에 할당하고 이를 레지스터에 저장한다고 가정합니다. 두 번째 명령어는 A와 관련이 없지만 레지스터를 점유해야 합니다(A가 있는 레지스터를 점유한다고 가정). 세 번째 명령어 이 명령어는 A의 값을 사용하며 두 번째 명령어와 독립적입니다. 그런 다음 순차 일관성 모델에 따르면 첫 번째 명령어가 실행된 후 A가 레지스터에 저장되고 두 번째 명령어가 실행될 때 A가 더 이상 존재하지 않으며 세 번째 명령어가 실행될 때 A가 다시 레지스터로 읽혀집니다. 이 과정에서 A의 값은 변경되지 않았습니다. 일반적으로 컴파일러는 두 번째 명령어와 세 번째 명령어의 위치를 ​​바꿔 A가 첫 번째 명령어 끝의 레지스터에 존재하도록 하고, 그런 다음 A의 값을 레지스터에서 직접 읽을 수 있어 반복 읽기의 오버헤드가 줄어듭니다.

파이프라인 재정렬의 중요성

최신 CPU는 거의 모두 파이프라인 메커니즘을 사용하여 명령 처리 속도를 높입니다. 일반적으로 명령을 처리하려면 여러 CPU 클럭 사이클이 필요하며 실행됩니다. 파이프라인을 통해 병렬로 여러 명령을 동일한 클록 주기에서 실행할 수 있습니다. 구체적인 방법은 명령을 읽기, 주소 지정, 구문 분석, 실행 및 기타 단계와 같은 서로 다른 실행 주기로 나누고 이를 위해 서로 다른 구성 요소에 배치하는 것입니다. 동시에, 실행 단위 EU에서 기능 단위는 덧셈 구성요소, 곱셈 구성요소, 로딩 구성요소, 저장 구성요소 등과 같은 다양한 구성요소로 분할되어 다양한 계산의 병렬 실행을 더욱 실현할 수 있습니다.

파이프라인 아키텍처는 명령이 순차 모델에서 고려되는 것이 아니라 병렬로 실행되어야 한다고 결정합니다. 재정렬은 파이프라인을 최대한 활용하여 수퍼스칼라 효과를 얻는 데 도움이 됩니다.

순서 보장

명령어가 반드시 작성된 순서대로 실행되는 것은 아니지만 단일 스레드 환경에서 명령 실행의 최종 효과는 다음과 같아야 한다는 점에는 의심의 여지가 없습니다. 효과는 순차적 실행에서도 일관됩니다. 그렇지 않으면 이 최적화는 의미가 없습니다.

일반적으로 명령어 재정렬이 컴파일 타임에 수행되든 런타임에 수행되든 위의 원칙이 충족됩니다.

Java 저장소 모델의 재정렬

JMM(Java 메모리 모델)에서 재정렬은 특히 동시 프로그래밍에서 매우 중요한 부분입니다. JMM은 작업 B를 실행하는 스레드가 작업 A를 실행하는 결과를 관찰하도록 하려면 사전 발생 규칙을 통해 순차적 실행 의미를 보장합니다. 그렇지 않으면 JVM이 임의 수행을 수행할 수 있습니다. 프로그램 성능을 향상시키기 위해 작업을 정렬합니다.

휘발성에 대한 작업은 모두 메인 메모리에 있고 메인 메모리는 모든 스레드에서 공유되므로 휘발성 키워드는 변수의 가시성을 보장할 수 있습니다. 여기서 대가는 성능이 희생되고 레지스터나 레지스터를 사용할 수 없다는 것입니다. . 캐시는 전역적이지 않기 때문에 가시성을 보장할 수 없으며 더티 읽기가 발생할 수 있습니다.

휘발성의 또 다른 기능은 재정렬을 방지하는 것입니다. 휘발성 변수에 대한 작업 지침은 재정렬되지 않습니다. 재정렬하면 가시성 문제가 발생할 수 있기 때문입니다.

가시성 확보 측면에서는 잠금(명시적 잠금 및 객체 잠금 포함)과 원자 변수 읽기 및 쓰기를 통해 변수의 가시성을 보장할 수 있습니다. 그러나 구현 방법은 약간 다릅니다. 예를 들어 동기화 잠금은 잠금이 해제될 때 캐시를 새로 고치기 위해 메모리에서 데이터를 다시 읽도록 합니다. 데이터는 표시되는 반면 휘발성 변수는 단순히 메모리를 읽고 씁니다.

JAVA에서의 JVM 재정렬에 대한 자세한 소개 및 관련 글은 PHP 중국어 홈페이지를 주목해주세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿