자바 메모리 모델 에 대한 심도 있 는 설명

자바 메모리 모델 은 자바 가상 컴퓨터 가 컴퓨터 메모리 와 어떻게 상호작용 을 하 는 지 보 여 주 며 다 중 스 레 드 읽 기와 쓰기 공유 메모리 의 자원 접근 문 제 를 해결 합 니 다.
메모리 모델
자바 가상 컴퓨터 의 메모리 모델 은 스 레 드 스 택 과 더 미 를 분리 하고 다음 그림 은 자바 메모리 모델 의 논리 도 를 묘사 합 니 다.

모든 스 레 드 는 자신의 스 레 드 스 택 이 어야 합 니 다.스 택 에는 스 레 드 가 현재 위치 에서 호출 하 는 방법 정 보 를 저장 하고 스 레 드 가 코드 를 실행 할 때 스 레 드 스 택 은 스 택 에 들 어가 고 스 택 에서 나 오 는 작업 을 계속 수행 합 니 다.
스 레 드 스 택 에 호출 된 모든 방법 에서 정 의 된 변 수 를 저장 하고 자신의 스 택 에 있 는 변 수 를 방문 합 니 다.다른 스 레 드 는 보이 지 않 습 니 다.두 스 레 드 가 같은 코드 를 실행 하 더 라 도 스 레 드 자체 스 택 에서 변 수 를 반복 합 니 다.하나의 스 레 드 는 변수 복사 본 을 다른 스 레 드 에 전달 할 수 있 지만 변수 자 체 를 공유 할 수 없습니다.
스 택 에서 변수 저장 형식 도 다 릅 니 다.기본 변수 형식(int,byte,long,boolean,char,double,float,short)에 속 하 는 변 수 는 변 수 를 스 택 에 직접 저장 하고 나머지 유형의 변 수 는 스 택 에 저장 되 며 스 레 드 스 택 에 서 는 가리 키 는 변수 주 소 를 가리 키 는 지침 만 유지 합 니 다.
더미 에는 자바 프로그램 에서 만 든 모든 대상 이 저장 되 어 있 습 니 다.어떤 스 레 드 가 만 들 어 졌 든 간 에.대상 을 만 들 고 부분 변수 에 할당 하거나 다른 대상 으로 만 든 구성원 변 수 는 영향 을 주지 않 습 니 다.이 대상 은 아직도 더미 에 저 장 됩 니 다.

주의해 야 할 것 은 자바 의 정적 클래스 변수 도 클래스 초기 화 에 따라 더미 에 저 장 됩 니 다.
대상 포인터 가 있 는 모든 스 레 드 는 쌓 인 대상 에 접근 할 수 있 습 니 다.스 레 드 가 대상 에 접근 할 수 있 을 때 이 대상 의 구성원 변 수 를 방문 할 수 있 습 니 다.만약 에 두 스 레 드 가 같은 대상 에서 하나의 방법 을 동시에 호출 하면 그들 은 모두 이 대상 의 구성원 변 수 를 방문 할 권리 가 있 지만 모든 스 레 드 는 자신의 국부 변수 사본 을 가지 게 될 것 이다.

두 스 레 드 는 쌓 인 공유 대상 을 가리 키 는 부분 변수 가 있 습 니 다.이 두 스 레 드 는 각각 같은 대상 에 대한 서로 다른 지침 을 가지 고 있다.그들의 포인터 도 부분 변수 이기 때문에 모든 스 레 드 스 택 에 저 장 됩 니 다(모든 스 레 드 에 있 습 니 다).그러나 두 개의 서로 다른 지침 은 쌓 여 있 는 같은 대상 을 가리킨다.
아래 의 코드 블록 은 바로 위의 그림 의 실제 예 이다.

public class MyRunnable implements Runnable() {

    public void run() {
        methodOne();
    }

    public void methodOne() {
        int localVariable1 = 45;
        MySharedObject localVariable2 = MySharedObject.sharedInstance;
        //...
        methodTwo();
    }

    public void methodTwo() {
        Integer localVariable1 = new Integer(99);
        //...
    }
}

public class MySharedObject {

    //static variable pointing to instance of MySharedObject
    public static final MySharedObject sharedInstance = new MySharedObject();

    //member variables pointing to two objects on the heap
    public Integer object2 = new Integer(22);
    public Integer object4 = new Integer(44);

    public long member1 = 12345;
    public long member2 = 67890;
}
하드웨어 구조
현대 하드웨어 의 메모리 구 조 는 자바 메모리 모델 과 약간 다 르 기 때문에 하드웨어 구 조 를 이해 하 는 것 이 자바 메모리 모델 을 이해 하 는 데 도 도움 이 된다.간단 한 하드웨어 구조 도 는 다음 과 같다.

현대 컴퓨터 는 일반적으로 다 핵 CPU 로 일반적으로 하나의 CPU 만 있 는 것 이 아니 기 때문에 여러 개의 스 레 드 는 물리 적 의미 에서 동시에 실 행 될 수 있다.이것 은 자바 응용 프로그램 이 다 중 스 레 드 라면 모든 CPU 가 자바 응용 프로그램 에서 하나의 스 레 드 를 동시에 실행 할 수 있다 는 것 을 의미한다.
모든 CPU 에는 하나의 레지스터 가 포함 되 어 있 는데,이 레지스터 들 은 본질 적 으로 CPU 메모리 저장 장치 이다.CPU 가 이 레지스터 에서 실행 하 는 속 도 는 메 인 메모리 의 변수 에 대한 실행 속도 보다 훨씬 빠르다.이것 은 CPU 가 메 인 메모리 에 접근 하 는 것 보다 이 레지스터 에 더 빨리 접근 할 수 있 기 때문이다.
모든 CPU 에는 CPU 캐 시가 있 을 수 있 습 니 다.실제로 대부분의 현대 CPU 는 일정한 크기 의 캐 시 를 가지 고 있다.CPU 는 메 인 메모리 보다 빠 른 속도 로 캐 시 에 접근 할 수 있 지만 내부 레지스터 에 접근 하 는 속도 가 빠 르 지 않 습 니 다.따라서 CPU 캐 시 메모 리 는 내부 레지스터 와 메 인 메모리 사이 의 속도 사이 에 있다.일부 CPU 에는 여러 개의 캐 시 계층(L1 과 L2 Cache)이 있 을 수 있 습 니 다.자바 메모리 모델 이 메모리 와 어떻게 상호작용 하 는 지 알 아 보 는 것 은 중요 하지 않 습 니 다.중요 한 것 은 CPU 가 특정한 캐 시 층 을 가 질 수 있다 는 것 을 알 아야 합 니 다.
컴퓨터 에는 메 인 저장 소(RAM)도 포함 되 어 있다.모든 CPU 는 메 인 메모리 에 접근 할 수 있다.메 인 저장 소 는 보통 CPU 의 캐 시 보다 훨씬 크다.
일반적으로 CPU 가 주 메모리 에 접근 해 야 할 때 일부 주 메모 리 를 CPU 캐 시 에 읽 습 니 다.캐 시 일부분 을 내부 레지스터 에 읽 고 실행 할 수도 있다.CPU 가 결 과 를 메 인 메모리 에 써 야 할 때 내부 레지스터 에서 캐 시 로 값 을 새로 고 친 다음 어느 때 값 을 메 인 메모리 로 새로 고 칩 니 다.
CPU 가 다른 내용 을 캐 시 에 저장 해 야 할 때 보통 캐 시 에 저 장 된 값 을 홈 메모리 로 리 셋 합 니 다.CPU 캐 시 는 한 번 에 데 이 터 를 메모리 에 기록 하고 한 번 에 메모리 일 부 를 새로 고 칠 수 있 습 니 다.업데이트 할 때마다 전체 캐 시 를 읽 거나 쓸 필요 가 없습니다.일반적으로 캐 시 는'캐 시 줄'이 라 고 불 리 는 작은 저장 블록 에서 업데이트 되 며,하나 이상 의 캐 시 줄 을 캐 시 메모리 에 읽 을 수 있 으 며,하나 이상 의 캐 시 줄 을 다시 메 인 메모리 로 갱신 할 수 있다.
자바 메모리 모델 과 하드웨어 연결
앞에서 말 한 바 와 같이 자바 메모리 모델 과 하드웨어 메모리 시스템 구 조 는 다 르 고 하드웨어 메모리 시스템 구 조 는 스 레 드 스 택 과 더 미 를 구분 할 수 없습니다.하드웨어 에 있어 서 스 레 드 스 택 과 더 미 는 모두 메 인 메모리 에 있 습 니 다.스 레 드 스 택 과 더미 의 일부 부분 은 CPU 캐 시 와 내부 CPU 레지스터 에 나타 날 수 있 습 니 다.아래 그림 은 이에 대해 설명 했다.

대상 과 변 수 는 컴퓨터 의 다양한 저장 영역 에 저장 할 수 있 을 때 문제 가 발생 할 수 있 습 니 다.두 가지 주요 문 제 는:
공유 변수의 가시 성 으로 스 레 드 업데이트(기록)4.567917.공유 변 수 를 읽 고 검사 하 며 기록 할 때의 경쟁 조건대상 의 가시 성
두 개 이상 의 스 레 드 가 하나의 대상 을 공유 하고 volatile 키 워드 를 정확하게 사용 하지 않 으 면 하나의 스 레 드 가 공유 대상 에 대한 업 데 이 트 는 다른 스 레 드 에 보이 지 않 을 수 있 습 니 다.
모든 스 레 드 는 공유 라 이브 러 리 복사 본 을 가지 고 있 으 며,각 복사 본 은 서로 다른 CPU 캐 시 에 있 습 니 다.공유 대상 이 최초 로 메 인 메모리 에 저장 되 었 다 고 상상 해 보 세 요.그리고 CPU 에서 실행 되 는 스 레 드 는 공유 대상 을 CPU 캐 시 에 읽 고 수정 합 니 다.CPU 캐 시 를 홈 메모리 로 리 셋 하지 않 으 면 다른 CPU 에서 실행 중인 스 레 드 에서 공유 대상 의 변경 버 전 을 볼 수 없습니다.
아래 그림 은 이러한 상황 을 설명 합 니 다.왼쪽 CPU 에서 실행 중인 스 레 드 는 공유 대상 을 CPU 캐 시 에 복사 하고 count 변 수 를 2 로 변경 합 니 다.오른쪽 CPU 에서 실행 중인 다른 스 레 드 는 이 변경 사항 을 볼 수 없습니다.count 를 홈 메모리 로 업데이트 하지 않 았 기 때 문 입 니 다.

물론 이 문 제 는 volatile 키 워드 를 사용 하여 해결 할 수 있다.
경쟁 조건
두 개 이상 의 스 레 드 가 한 대상 을 공유 하고 한 개 이상 의 스 레 드 가 공유 대상 의 변 수 를 업데이트 하면 경쟁 조건 이 발생 할 수 있 습 니 다.
스 레 드 A 가 공유 대상 의 변 수 를 CPU 캐 시 에 읽 고 스 레 드 B 가 같은 동작 을 수행 하지만 서로 다른 CPU 캐 시 에 있 습 니 다.현재 스 레 드 A 에 계산 을 추가 하고 스 레 드 B 도 같은 동작 을 수행 합 니 다.현재 count 는 두 번 추가 되 었 습 니 다.CPU 캐 시 마다 한 번 씩 추가 되 었 습 니 다.
이 증가 가 순서대로 실 행 될 경우 변수 수 는 두 번 증가 하고 원시 값+2 를 메 인 메모리 에 다시 씁 니 다.
그러나 이 두 증 가 는 동기 화 되 지 않 은 상태 에서 동시에 실 행 된 것 이다.스 레 드 A 와 B 의 어느 스 레 드 가 업 데 이 트 된 버 전 을 메 인 메모리 에 쓰 든 두 개의 증 가 는 있 지만 업 데 이 트 된 값 은 원본 값 보다 1 높 습 니 다.
이 그림 은 상기 와 같은 경쟁 조건 문제 의 발생 을 설명 한다.

이 문 제 는 synchronized 키 워드 를 사용 하여 해결 할 수 있 습 니 다.
총결산
자바 메모리 모델 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.자바 메모리 모델 에 관 한 더 많은 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 바 랍 니 다!

좋은 웹페이지 즐겨찾기