심층 자바 메모리 모델 (A)의 이해

카테고리 동시 프로그래밍 모델

동시 프로그래밍에서, 우리는 주소로 두 가지 핵심 문제를 필요 스레드 및 방법 (여기 스레드 활성 개체 동시 실행입니다) 스레드간에 동기화하는 사이에 통신하는 방법. 어느 스레드 간의 정보 교환의 통신기구를 말한다. 프로그래밍 명령은, 두 개의 쓰레드 간 통신 메커니즘 : 공유 메모리, 메시지 전달.

공유 메모리 동시성 모델에서 작성하여 스레드의 스레드 사이의 일반적인 상태 공유 프로그램 - 암시 적으로 공통의 상태가 메모리를 읽을 통신합니다. 동시성 모델 메시징에서 국가 사이에 공통점이없는, 명시 적으로 스레드간에 명시 적 메시지를 전송하여 통신해야합니다.

이것은 다른 스레드의 발생을 제어하기위한 운영 프로그램과의 동기기구의 상대적인 순서를 말한다. 공유 메모리 동시성 모델에서 명시 적으로 동기화를 수행한다. 프로그래머는 명시 적 방법 또는 코드의 조각이 스레드간에 상호 배제를 수행하는 데 필요한 지정해야합니다. 동시성 모델의 메시징 년부터 메시지를 수신하기 전에 전송 메시지 따라서 암시 적 동기화를 수행해야합니다.

자바 동시성은 공유 메모리 모델을 사용, 자바 스레드 사이의 통신은 항상 암시 적으로 수행되며, 전체 통신 과정은 프로그래머에게 완전히 투명합니다. 당신은 자바 프로그래머가 암시 적으로 수행 스레드 사이의 통신의 작동 메커니즘을 이해하지 못하는 다중 스레드 프로그램을 작성하는 경우, 이상한 메모리 가시성 모든 종류의 문제가 발생할 가능성이 높습니다.

추상 자바 메모리 모델

자바 힙 메모리에 저장된 모든 인스턴스 필드 정적 필드 및 어레이 소자는, 상기 공유 메모리 힙 스레드 간 (AS는 본원에서 사용 "공유 변수"인스턴스 필드 기간, 정적 필드 및 배열 요소의 생성을 의미한다). 지역 변수 (지역 변수), 방법, 그들은 메모리 문제의 가시성을하지 않아도, 스레드간에 공유되지 않는 매개 변수 (자바 언어 사양은 형식 메서드 매개 변수라고도 함)와 예외 핸들러의 매개 변수 (예외 핸들러의 매개 변수)를 정의하는 방법도 메모리 모델에 영향을 미치는하여.

스레드 간의 통신은 자바 자바 메모리 모델 (본원 JMM라고 함)에 의해 제어된다 JMM 때 다른 스레드 표시 공유 변수 스레드 쓰기를 결정한다. 메인 메모리 (메인 메모리), 각 스레드는 전용 로컬 메모리 (로컬 메모리)가 가변 스레드간에 공유 스토리지 : 추상적 인 관점에서, JMM 스레드와 메인 메모리 사이의 관계를 정의 추상 읽기 / 쓰기 위해 스레드의 복사본을 저장 로컬 메모리 공유 변수. JMM 로컬 메모리는 추상적 인 개념이며, 실제 아니다. 그것은 캐시, 쓰기 버퍼, 레지스터 및 기타 하드웨어 및 컴파일러 최적화를 포함한다. 다음과 같이 자바 메모리 모델의 추상 그림은 다음과 같습니다 :

                     심층 자바 메모리 모델 (A)의 이해 - 기본

지도보기에서, 스레드 A와 B 사이에 스레드가 전달 될, 그것은 다음과 같은 두 단계를 거쳐야합니다 있습니다 :

  1. 우선, 갱신 스레드 A의 로컬 메모리 A는 공유 변수는 메인 메모리로 플러시된다.
  2. 스레드 A는 공유 변수를 업데이트하기 전에 그리고, 스레드 B는 메인 메모리에 판독한다.

개략도는 다음의 두 단계로 설명한다 :

                     심층 자바 메모리 모델 (A)의 이해 - 기본

상술 한 바와 같이, A 및 B는 공유 변수 x의 메인 메모리에 복사 로컬 메모리를 갖는다. 초기 가정하면, 이들 3 개 개의 메모리의 X 값은 0이다. 스레드는 실행시에 일시적 A. 자체 로컬 메모리에 저장된 x의 값을 (1의 값을 가정) 업데이트 스레드 A 및 스레드 B가 통신을 요구하는 경우, x의 스레드가 제 1 값은 주 메모리는 1이된다 이때, 로컬 메모리 수정 후 메인 메모리에 X의 값을 플러시 소유. 이어서, 메인 메모리에 스레드 B가 갱신 스레드 A 후, x의 값은 스레드 B의 로컬 메모리는 1이된다이 때, X의 값을 판독한다.

전반적으로, 스레드 A는 스레드에 실질적으로 두 단계 B에 메시지를 전송하고, 상기 통신 과정은 메인 메모리를 통해 이동한다. 메모리 보장 자바 프로그래머의 시야를 제공하기 위해, 주기억 각 스레드의 로컬 메모리 사이의 상호 작용을 제어함으로써 JMM.

순서 변경

프로그램을 실행할 때 성능을 개선하기 위해, 컴파일러 프로세서 명령어는 종종 재 배열 될 것이다. 세 가지 유형의 재정렬 :

  1. 컴파일러 최적화 재정렬. 전제의 의미를 변경하지 않고 단일 스레드 프로그램 컴파일러, 당신은 명령문의 실행의 순서를 다시 정렬 할 수 있습니다.
  2. ILP 재정렬. 현대 프로세서 채용 명령어 수준 병렬화 (명령어 수준 병렬성 ILP)은 실행 된 명령의 복수의 중첩. 데이터 의존성이 존재하지 않는 경우, 상기 프로세서는 명령문 시퀀스에 대응하는 컴퓨터 명령들의 실행을 변경할 수있다.
  3. 시스템의 메모리를 재정렬. 프로세서는 캐시와로드 및 저장 동작이 순서가 나타나는 실행하게 판독 / 기록 버퍼를 사용하기 때문이다.

실제로 실행되는 명령어의 순서로 최종 소스 코드에서 자바는 각각 재정렬 다음과 같은 세 가지를 받게 될 것이다 :

심층 자바 메모리 모델 (A)의 이해 - 기본

컴파일 존중 2 정렬 상기 1, 3 프로세서를 재정렬한다. 순서 정렬은 멀티 스레드 프로그램 메모리 가시성 문제가 발생할 수 있습니다. 컴파일러는 JMM의 관심을 컴파일하려면 정렬 규칙은 컴파일러의 특정 유형이 매우 정렬 (모든 컴파일러가 낙담 한하지가 종류의 금지)의 생각 금지합니다. 하여 메모리 배리어 명령의 특정 타입을 해제하는 명령들의 시퀀스, 메모리 배리어 인서트의 특정 유형 (메모리 배리어 인텔 불리는 메모리 울타리) 명령을 생성 할 때 프로세서 재정렬 프로세서 JMM 재정렬 규칙 자바 컴파일러 항 프로세서 재정렬 (모든 프로세서는 재정렬을 금지한다).

언어 수준의 메모리 모델에, 그것은 다른 컴파일러와 다른 프로세서 플랫폼에 보장 속해 JMM은 주문 및 메모리의 특정 유형의 프로그래머를위한 일관된 가시성 보장을 제공 금지 재정렬 프로세서 컴파일러에 의해 낙담.

프로세서 및 메모리 배리어 명령 재정렬

현대의 프로세서는 일시적 저장에 쓰기 버퍼 메모리에 기록 된 데이터를 사용합니다. 기록 버퍼 명령 파이프 라인은 생성 된 메모리 지연 기록 데이터를 기다리고 중단 프로세서를 방지 할 수 있고, 연속적인 동작을 보장 할 수있다. 한편, 배치 모드 새로 고침 쓰기 버퍼에, 동일한 메모리 주소에 여러 쓰기 버퍼 쓰기를 병합, 당신은 메모리 버스의 점유율을 줄일 수 있습니다. 이렇게 많은 장점이 있습니다 버퍼 쓰기,하지만 각 프로세서의 쓰기 버퍼, 프로세서는 유일한 곳은 볼 수 있지만. 이 실행 메모리 작업 중요한 영향을의 순차적 특성을 생성합니다 프로세서 메모리 읽기 / 쓰기 동작을 실행하기 위해, 반드시 실제 메모리는 동일한 순서로 읽기 / 쓰기 작업을! 설명하기 위해 다음 예제를 고려하십시오

프로세서 A를 프로세서 B
A = 1; // A1

X = B; // A2
B = 2; // B1의

Y는 =; // B2
초기 상태 A는 = 0 B =를

, 상기 프로세서는 실행 결과를 얻을 수 있도록, X = Y = 0

메모리는 프로세서 A 및 B 프로세서 프로그램 순서가 병렬로 수행 액세스하는 것으로 가정 최종 X = Y = 0의 결과를 얻을 수있다. 아래에 도시 된 바와 같이 구체적인 이유 :

                        심층 자바 메모리 모델 (A)의 이해 - 기본

여기서 프로세서 A 및 프로세서 B는 공유 변수 기록 버퍼 (A1, B1)에 동시에 기록 될 수 있고, 그리고 메모리에서 다른 공유 변수 (A2, B2)를 판독하고, 단지 다음 자신의 마지막 버퍼를 쓰기 메모리 (A3, B3)에 저장된 더티 데이터를 새로. 이 시점에서 수행되는 경우, 프로그램은 결과 X = Y = 0을 얻을 수있다.

프로세서 A는 자신의 기록 버퍼를 새로 A3를 수행 할 때까지 동작은, 관점, 실제 메모리의 주문, A1 진정 구현 쓴다. 같은 순차 처리 A를 행한다 메모리 동작이지만 : A1-> A2 있지만, 메모리 동작의 실제 시퀀스이다 A2-> A1. 이때, 순차 프로세서 A는 메모리 동작을 재정렬는 (프로세서 A 및 B 프로세서가 동일한 경우, 여기에 이동하지 않음)이다.

키 여기 의한 기록 버퍼에, 그 인 것은 단지 자신의 프로세서에 표시되고 그 메모리 동작의 순서의 실제 구현과 일치하지 않을 수 메모리 동작을 수행하는 일련의 프로세서로 이어질 것이다. 최신 프로세서는 쓰기 버퍼를 사용하기 때문에, 그래서 현대의 프로세서는 쓰기 수 - 재정렬 체조을 읽어 보시기 바랍니다.

여기 유형을 재정렬 허용 일반적인 프로세서의 목록입니다 :

  로드로드 로드 - 스토어 쇼핑몰 저장소 스토어 -로드 데이터 종속성
SPARC-TSO
86
IA64
파워

셀 테이블 "N"은 두 개의 프로세서가 재정렬 동작을 허용하지 않는 것을 나타내고, "Y"는 허용 리오 더링을 나타낸다.

우리는 테이블에서 볼 수 일반적인 프로세서는 재정렬 스토어 -로드 할 수 있습니다, 일반적인 프로세서 작업은 재정렬 할 데이터의 존재에 의존 할 수 있습니다. SPARC-TSO 및 x86 프로세서는 상대적으로 강한 메모리 모델을 가지고, 그들은 단지 쓰기 허용 - 읽기 재정렬 할 (때문에 둘 다 사용 쓰기 버퍼).

※ 주 1 : SPARC-TSO가 TSO에 수단을 운영 (총 스토어 주문) 메모리 모델, SPARC 프로세서의 특징.

※ 주 2 : 위의 표는 86 x64 및 AMD64 포함되어 있습니다.

※ 주 3 : 메모리 모델 ARM 프로세서와 메모리 모델은 PowerPC 프로세서와 매우 유사합니다, 우리는 그것을 무시합니다.

※ 주 4 : 특히 데이터 종속성을 설명하는 텍스트입니다.

메모리의 가시성을 보장하기 위해, 자바 컴파일러 프로세서 재정렬 특정 유형을 사용하지 않도록 삽입 된 메모리 배리어 명령의 적절한 위치 명령 시퀀스를 생성. 메모리 배리어 명령 JMM은 다음의 네 가지 범주로 구분 :

장벽 유형 INSTRUCTION 설명
LoadLoad 장벽 로드 1; LoadLoad; 로드 2 데이터를 확인로드 1로드 및 모든 후속 적재 명령로드 2 로딩 이전된다.
StoreStore 장벽 상점 만들기; StoreStore; 상점 2 상점 만들기 이전에 저장된 다른 상점 2 프로세서 (리프레시 메모리) 이후의 모든 저장 명령에 표시 데이터를 보장한다.
LoadStore 장벽 로드 1; LoadStore; 상점 2 메모리 리프레시 이후의 모든 저장 명령 데이터가로드되어 있는지 확인하고 상점 2 이전에로드 1.
StoreLoad 장벽 상점 만들기; 대형로드; 로드 2 상점 만들기 데이터 확인은로드 2 로딩 전에 다른 프로세서에 대한 모든 후속 적재 명령에서 (리프레시 메모리 참조) 표시된다. 장벽 전에 모든 메모리 접근 명령어 (로드 및 저장 명령어) 후 StoreLoad의 장벽 장벽 후 메모리 액세스 명령어의 실행 전에 완료됩니다.

StoreLoad 방벽은 또한 세 가지 다른 장벽의 영향을하는 "만능"장벽이다. 장벽에 대한 대부분의 최신 멀티 프로세서 지원 (장벽의 다른 유형은 반드시 모든 프로세서를 지원하지 않습니다). 현재 프로세서는 일반적으로 리프레시 메모리 버퍼에있는 모든 데이터를 기록 할 때문에 배리어 헤드의 구현이 매우 비싼 것 (완전 세척 버퍼).

발생-전에

처음부터 JDK5 새로운 JSR -133 메모리 모델 (이하, 특별히 언급하지 않는 한, 메모리 모델이다 JSR-133)를 이용하여 자바. JSR-133-발생하기 전에이 개념에 의해 제안 된 개념은 메모리 간의 가시성의 동작을 설명하기. 수행되는 동작의 결과가 표시가 필요한 경우, 이전에 발생-관계가 다른 연산에 대한 두 가지 동작 사이에 존재한다. 두 작업 본원 스레드간에 상이 할 수 있고, 쓰레드 중 어느 하나 일 수있다 지칭. 발생-하기 전에 다음과 같은 규칙이 밀접 프로그래머 관련이 있습니다 :

  • 프로그램 순서 규칙 : 스레드에 대한 후속 작업을하기 전에 적 있었 각 작업 스레드.
  • 모니터 잠금 규칙 : 모니터가 잠금을 해제,이 모니터 잠금 장치를 고정하기 전에 다음 적 있었.
  • 휘발성 변수 규칙 : 휘발성 필드에 대한 쓰기, 어떤 후속이 휘발성 영역을 읽기 전에 적 있었.
  • 트랜 A는 B 전에 적 있었 및 B가 C 전 적 있었 경우, 다음 적 있었 C. 전

참고는 발생-전에 함께 두 작업 사이의 관계, 사전 작업을 한 후 작동하기 전에 수행되어야한다는 것을 의미하지 않습니다! 이 미연 - 제 2 동작 전에 표시 및 시퀀싱 이전 작업의 작업 후에 하나의 동작 (실행 결과)가 필요하기 전에 (제 볼 및 초 전에 순서 임). 정의는 매우 섬세하기 전에 이렇게 발생-전에 왜 정의 텍스트를 지정합니다 적 있었.

JMM 발생-전에 다음 그림과의 관계 :

                      심층 자바 메모리 모델 (A)의 이해 - 기본

위와 같이, 규칙 발생-전에 컴파일 일반적으로 프로세서의 복수에 대응하고 조합 규칙을 재정렬 낙담. 자바 프로그래머의 경우, 발생-전에 규칙이 간단하고 이해하기 쉬운, 멀리 복잡한 재정렬 규칙의 구체적인 구현을 배울 수 JMM에서 제공하는 메모리 보장의 가시성, 그리고 이러한 규칙을 이해하는 프로그래머를 피할 수 있습니다.

 

게시 된 136 개 원래 기사 · 원 찬양 6 · 전망 1492

추천

출처blog.csdn.net/weixin_42073629/article/details/104741348