예술 자바 병행 프로그래밍 (9) 최종

읽기 및 쓰기 마지막 필드는 더 일반 변수 액세스 같다

최종 규칙 재정렬 도메인

최종 도메인의 경우, 컴파일러와 프로세서는 두 개의 재주문 규칙을 준수합니다.
(1) 최종 필드의 생성자에 기록하고 참조하는 오브젝트가 참조 변수에 할당 된이 구성은, 재정렬이 두 작업 사이 아니다.
(2) 최종적인 기준을 포함하는 제 1 목표 영역을 판독 한 후 최종 초기 필드 판독은, 재정렬이 두 작업 사이 아니다.

public class FinalExample {
    int i;普通变量
    final int j;final变量
    static FinalExample obj;
    public FinalExample() {  构造函数 
        i = 1;  写普通域 
        j = 2;final}
    public static void writer() {  写线程A执行 
        obj = new FinalExample();
    }
    public static void reader() {  读线程B执行 
        FinalExample object = obj;  读对象引用 
        int a = object.i;  读普通域 
        int b = object.j;final}
}

기록기 스레드 A가 실행을 가정한다 (다른 스레드 B 하였다)에있어서, 판독기 () 메소드를 실행.

쓰기 재정렬 최종 도메인 규칙

글 마지막 필드 재정렬 규칙은 생성자 외부의 마지막 필드를 재정렬 쓰기를 금지합니다.
(1)은 재정렬 JMM 최종 필드를 외부 생성자 물품 컴파일러 방지한다.
(2) 컴파일러가 최종 필드 후 작성합니다하기 전에 StoreStore 장벽 삽입 생성자 반환. 이 장벽은 생성자 외부의 마지막 필드를 재정렬 쓸 수있는 프로세서를 금지합니다.
라이터 () 메소드
(1) 타입 FinalExample의 객체를 생성한다.
(2) 오브젝트 참조 변수 OBJ 참조하여 할당.
수 있도록 규칙을 재정렬 글 마지막 필드 :
볼, 최종 도메인 객체 전에 스레드에 대한 참조를 올바르게 개체 위에 초기화되었습니다.
이 도메인은 통상의 보안 쓰레드 B 오브젝트 레퍼런스 OBJ 아마도 아직 생성되지 않은 오브젝트 OBJ (나는 정규 도메인 물품 외부 생성자, 또한 초기 값을 재 배열 할 때 "볼"이없는 공통 도메인 내가 작성하지)
그림 삽입 설명 여기

최종 규정 재정렬 도메인 읽기

스레드에서 판독 필드 최종 규정 재정렬, 제 1 판독 영역의 기준 시온 최종 판독하고 객체는 두 동작들을 재정렬 JMM 금지 프로세서를 포함한다. LoadLoad 컴파일러는 최종 읽기 도메인 작업의 앞에 장벽을 삽입합니다.
판독 우선 초기 판독 최종 개체 참조 필드는 객체의 두 동작 간의 간접 종속성을 포함한다. 컴파일러 준수 간접 의존성 때문에, 컴파일러는이 두 작업의 재정렬을 수행합니다.
Reder () 메소드는 세 개의 동작이 포함
(1)의 초기의 판독 기준 변수 OBJ
객체 일반 도메인 J 가리키는 obj를 (2) 초기의 판독 기준 변수
i가 가리키는 오브젝트 최종 필드 obj를. (3) 제 1 판독 기준 변수
라이터 스레드 A가 발생하지 않은 것으로 간주 됨 모든 재정렬하고, 프로그램 실행이 프로세서에 간접적으로 의존 따르지 않는
그림 삽입 설명 여기
일반적인 도메인 오브젝트를 판독하기위한 동작은 오브젝트 레퍼런스를 판독하도록 프로세서 전에 재 배열된다. 독서이 잘못 읽기 작업이며, 도메인이 스레드 A가 기록 된 기록되지 않은 일반적인 도메인입니다. 최종 판독 동작 필드 규칙 마지막 스레드 A 도메인을 초기화 된 시간에 객체 참조를 판독 한 후 "정의"재정렬 최종 타겟 영역을 읽을 것이고, 이는 적절한 판독 동작 동안
최종 필드를 읽어 재정렬 규칙은 확인 : 대상 도메인의 마지막 읽기 전에, 우리는 먼저 최종 필드에 개체 참조가 포함 읽습니다. 참조가 null가 아닌 경우,이 예에서, 다음 객체 참조 최종 도메인 이전 스레드를 초기화해야합니다.

최종 필드는 참조 형

public class FinalReferenceExample {
    final int[] intArray;  final是引用类型
    static FinalReferenceExample obj;
    public FinalReferenceExample() {  构造函数
        intArray = new int[1];        1 
        intArray[0] = 1;              2 
    }
    public static void writerOne() {  写线程A执行 
        obj = new FinalReferenceExample();   3 
    }
    public static void writerTwo() {   写线程B执行 
        obj.intArray[0] = 2;                 4
    }
    public static void reader() {  读线程C执行 
        if (obj != null) {                   5
            int temp1 = obj.intArray[0];     6 
        }
    }
}

기준 유형의 기록 필드 최종 재정렬 컴파일러 규칙 프로세서는 다음의 제약 조건을 추가
하여 최종 기준 객체의 생성자 도메인의 부재를 작성하고,이 후, 객체의 생성자 외부 구성된 변수에 할당 기준에 대한 참조는, 두 간격이 재정렬 동작 할
리더 스레드 JMM을 보장하지만 볼 수 이상의 기입 C에서 마지막으로 도메인 객체 기준 부재에 기록 생성자 스레드.
어레이의 적어도 1로 표시되는, 즉 0에서 C 표시한다. 작가 스레드 B는 볼 수없는, 쓰기 배열 요소, 읽기 스레드 C가 표시 될 수 있습니다.
JMM은 데이터 읽기 및 쓰기 스레드 B 스레드 C는이 시간에 결과를 예측할 수 사이에 경쟁이 있기 때문에 볼 쓰기 스레드 B 스레드 C를 읽을 보장 할 수 없습니다.
당신이 읽기 쓰기 스레드 B 스레드가 쓰기, 쓰기에 배열 요소를 참조 C 있는지 확인하려면, 메모리 스레드 가시성을 읽을 수 있도록 스레드 B와 C 사이의 동기화 프리미티브 (잠금 또는 휘발성)의 사용을 필요로한다.

당신은 최종 참조 생성자에서 벗어날 수 없다

어떤 스레드가 최종 개체 변수 도메인의 기준점으로 참조 변수에서 볼 수 있습니다 전에 제대로 생성자에서 초기화되었습니다 서면 최종 필드 재정렬 규칙이 있음을 확인합니다. 이 효과를 얻으려면, 당신은 또한 보증이 필요합니다 내부 생성자, 더 이상 객체 참조 생성자 탈출입니다 볼 수있는 다른 스레드에 대해이 구조화 된 객체 참조를 만들기 위해 뛰었다.

public class FinalReferenceEscapeExample {
    final int i;
    static FinalReferenceEscapeExample obj;
    public FinalReferenceEscapeExample() {
        i = 1;            1final域 
        obj = this;       2 this引用在此"逸出" 
    }

    public static void writer() {
        new FinalReferenceEscapeExample();
    }

    public static void reader() {
        if (obj != null) {      3 
            int temp = obj.i;   4 
        }
    }
}

그림 삽입 설명 여기
() 메소드 wirter 스레드 A가 실행하는 가정을, 다른 스레드 B 리더 () 메소드를 실행. 2 동작 객체 여기 스레드 B 전에 가시광으로 구성되도록 완성되지 않았다. 2 여기에 작업이 생성자의 마지막 단계, 및 운영 1의 방법 뒤에 2 행의 작업 스레드 경우에도, 당신은 프로그램의 마지막 필드의 구덩이 여전히 초기화 값을 볼 수 없습니다) (읽기 실시합니다 여기 한 동작 때문에 작업은 2 사이에 다시 정렬 할 수있다
그림 삽입 설명 여기
참조 된 개체가 도메인가 초기화되지 않았기 때문에, 최종 구성된 다른 스레드를 위해 보이지 않는 생성자를 반환하기 전에. 생성자가 반환 된 후, 임의의 스레드에 최종 필드가 제대로 초기화 후 가치를 보장합니다.

JSR-133 의미 최종 향상된

기존의 자바 메모리 모델에서 가장 심각한 결함 중 하나는 스레드가 마지막 필드의 값이 변경됩니다 볼 수 있습니다.
(스레드는 현재 최종 필드 (기본 값은 전에 초기화되지 않은)를 0으로 설정 정수를 볼 때 예를 들어, 갈 시간이 지나면이 분야의 스레드 최종 값을 읽을 수 있지만 값을 1로 발견 초기화 후에 스레드 값).
가장 일반적인 예는 기존의 자바 메모리 모델, 문자열의 값이 변경 될 수 있습니다.
이러한 취약점을 해결하기 위해, JSR-133 전문가 그룹은 최종 시맨틱을 향상시킨다.
최종 읽기 - 쓰기 및 재 주문 규칙에 대한 필드를 증가하여, 초기화는 자바 프로그래머에 대한 보안을 제공 할 수 있습니다 개체만큼 긴 제대로 구성되어 (생성자 건설 개체에는 "탈출"을 인용 없음), 동기식 사용할 필요가 없습니다 값 (잠금 휘발성의 사용을 의미한다) 모든 스레드가 마지막 필드 후 생성자 초기화 볼 수 있도록 할

게시 24 개 원래 기사 · 원 찬양 1 · 조회수 543

추천

출처blog.csdn.net/qq_45366515/article/details/105146305