고성능 프로그래밍 - 잠금 (동기화 심층 분석) 관련 자바 스레드 안전 문제

자바에서 잠금의 개념

사실, 이미 원자를 설명하기 이전 장에서 언급 잠금을 썼다, 그러나 이것은 자바에 대한 잠금은 잠금과 관련된 몇 가지 개념을 소개 여기에, 배울 여전히 많은 것들,하지 충분하다.

스핀 락

그것은 잠금이 다른 스레드에 의해 인수 된 경우 스레드가 잠금을 획득 할 수있는 시간을 의미, 다음 스레드주기 위해 대기하고 잠금 루프를 종료합니다 인수 될 때까지 잠금이 성공적으로 인수 여부를 결정하는 것을 계속한다.
그림 삽입 설명 여기
그림은 전형적인 시나리오이다 로크주기를 획득하는 과정은 회전에서와 동일하다.

낙관적 잠금

충돌을 가정하지, 일치하지 않는 데이터를 발견하고 이전에 구입 한 경우, 다음 데이터가 수정 될 때, 수정 된 재시도 수정 한 최신 데이터를 읽습니다. 독서 시간과 다른 시간, 잠겨 있지 만 수정하기 전에 고정.

비관적 잠금

동시성 충돌이 발생한다고 가정 데이터에 관련된 모든 작업을 동기화, 데이터가 처음부터 읽어 잠겨. 이 데이터는 가두 처음부터 읽습니다.

독점 잠금 (쓰기 잠금)

쓰기 잠금에 자원을 추가 자원을 수정할 수 있습니다 스레드는 다른 스레드를 잠글 수 없습니다 (쓰기 번)

공유 잠금 (읽기 잠금)

잠금을 읽을 자원을 추가 한 후 읽기 전용 있지만 변경할 수는 없습니다, 다른 스레드는 읽기 잠금을 추가 할 수 있습니다, 쓰기 잠금을 추가 할 수 없습니다 (자세히보기)

재진입 잠금, 잠금 재진입하지 않습니다

스레드 후 소위 재진입 값은 같은 잠금 동기화하여 다른 코드를 입력 자유롭게 잠금을 얻었다.

공정 잠금, 불공정 잠금

잡아 잠금 주문 잠금을 잡아 잡아 잠금 잠금 공정 인 순서 있는지 확인하기 위해서입니다.

동기화 동기화 키워드

  1. 방법, 정적 방법의 예는 암시 적으로 잠금 객체를 지정
  2. 사용되는 코드 블록은 지정된 락 객체로
  3. 잠금 범위 : 오브젝트 잠금, 잠금 클래스, 분산 잠금
  4. 아이디어 : 경우 더 이상의 프로세스, 어떻게합니까?

알고 동기화

class Counter{

    private static int i=0;

    //synchronized(this){}
    public synchronized void update(){
        //访问数据库
    }

    public void updateBlock(){
        synchronized (this){
            //访问数据库
        }
    }

    //synchronized(Counter.class)
    public static synchronized void staticUpdate(){
        //访问数据库
    }
    
    public static void staticUpdateBlock(){
        synchronized(Counter.class){
            //访问数据库
        }
    }
}

위의 의사 코드에서 동기화의 사용 개요, 우리는 잠금 과정이다 동기 분명해야하지만, 내부 JVM의 일련의 아웃 처리 후이 잠금 또는 Counter.class 아니라.

동기화 기능

재진입은, 독점, 비관적 잠금을 동기화됩니다. 그것은 또한 잠금 잠금 조 최적화로, 제거를 잠급니다.

잠금 제거

아이디어는 과정은 실시간 JIT 컴파일 시간에 발생, 잠금 수단을 제거 할 수 있습니다, 특정 상황에서 잠금을 제거하는 것입니다. 코드 조각 봐 :

public void test1(Object arg){

        //StringBuilder线程不安全,StringBuffer用了synchronized,是线程安全的
        // jit 优化,消除了锁
        StringBuffer stringBuffer = new StringBuffer(); //局部变量,没有在其他线程中使用
        stringBuffer.append("a");
        stringBuffer.append("b");
        stringBuffer.append("c");

        stringBuffer.append("a");
        stringBuffer.append("b");
        stringBuffer.append("c");

        stringBuffer.append("a");
        stringBuffer.append("b");
        stringBuffer.append("c");
//        System.out.println(stringBuffer.toString());;
    }

행동 할 실행될 상기 코드의 실행의 시작하지만,이 방법은 JIT 컴파일러를 트리거 여러 번 수행 될 때, 그 때 제거 로크 인 동기화 키워드를 제거하는 것이기 때문에. 참고 그러나,이 상황은 단일 스레드 경우에 존재합니다.

锁粗 화

세밀한 잠금을 향상 성능을 향상시키기 위해, 동기의 코드 사이에서 세밀한 저를 많이 넣어하는 데 사용됩니다. 예를 들어
그림 삽입 설명 여기
동작이 작은 쪽 위의 프레임은 다음과 같이 JVM을 최적화한다.

학습의 동기 원칙

원칙은 먼저 잠금이 객체를 잠그는 것입니다 방법을 알고 가야 실현하기 위해서는 잠겨 상태는 어떻게 기록하는 것입니다? 국가는이 객체 거기에 기록됩니다? 잠금이 점령되면, 잠금 스레드가 스레드가 눈을 뜨고 큐 큐의 선두를 중단 할 때 잠금이 해제 될 때 정지됩니다 적용됩니다. 위의 메커니즘에, 학습의 지식에 관련된 객체에 깊이 갈 필요가있다 :

자바 객체 저장 원리

코드로보고, 자바 메모리 모델 :
그림 삽입 설명 여기
그림 삽입 설명 여기
직접적 메인 스레드의 로컬 변수 테이블에 저장된 로컬 변수의 기본적인 유형, 기준 제임스 로컬 변수 테이블도 존재 첫 번째는 1 = int로.

: 클래스 멤버 변수는 객체의 힙 메모리에 존재합니다
그림 삽입 설명 여기
메소드 영역에 저장되어있는 정적 변수, 방법 (정적 및 비 정적), 그리고 당신은 그들이 메소드 지점으로 객체 헤드에 의존 할 정보를 얻으려면 객체 지역 클래스입니다. 당신은 초기 변수와 메소드를 얻을 수 있습니다. 심지어 참고 문헌에주의가 직접 다른 객체를 가리키는 객체에 저장하고, 객체는 지정된 클래스 객체 헤더를 찾을 통과하고 있습니다 :
그림 삽입 설명 여기

자세한 객체 헤더

우리는 표시 객체 저장 선두 상세지도를 살펴 보자,에 객체 헤더에 실제로, 마크를 잡기 위해 잠금을 변경해야합니다 :
그림 삽입 설명 여기

마크 워드

잠금에 마크의 마크 워드 (태그 필드)에 저장됩니다. 그것은 본질적으로 메모리에 힙 메모리 영역의 기간이다. 크기는 64 비트 (32 비트 시스템에 대한 32 비트)이다.
그림 삽입 설명 여기
마크 말씀의 위의 다섯 개 가지 상태.
잠금과 결합되지 않도록 처음으로 표시 말씀합니다. 둘째 단락 잠금 편향된다. 세 번째 단락은 경량 잠금입니다. 네 번째 단락은 헤비급 잠금입니다.

업그레이드 프로세스를 잠금

그림 삽입 설명 여기

바이어스 잠금

사실 바이어스 잠금 후, 스레드 장면에만 유용 잠금 후 사실, 더 이상 잠금 해제를, ID 스레드에 0을 변경, 아무 소용이 없었다. -UseBiasedLocking 해제 바이어스 잠금 : JVM 매개 변수는 -XX를 사용할 수있다.

바이어스 잠금, 본질적으로 잠금, 잠금에 대한 멀티 스레딩 경쟁이 발생하지 않은 경우, JVM은 그 단일 스레드라고 생각하지, 당신은 동기화 할 필요가 없습니다

경량 잠금

먼저 마크 말씀이 스택 프레임 동기 코드 블록에 복사 할 때 잠 깁니다, 다음 자신의 잠금 기록 주소를 잡기 위해 모든 스레드 CAS 작업, 나사 잠금 장치를 적용, 다른 스레드가 CAS를 성공하지 수 있도록 작성 어떤 스레드는 에스컬레이션을 잠급니다 어느 정도 성공 스핀 요구하지 않습니다.

헤비급 잠금

경량 잠금 스핀 잠금을 적용했을 경우 헤비급 잠금 업그레이드, 잠금이 다시 일어나 잠금을 해제 할 때 스레드 현탁액하는 entryList에 저장되어 적용하는 것입니다, 그래서, CPU의 성능을 소모한다.

클래스 메타 주소

사용 클래스 영역에있어서 어드레스를 참조하는 경우 객체 초기화, 포인터에 대응한다.

배열의 길이

대상체가 배열되는 경우 배열의 길이는 다음의 길이를 기록한다.

게시 38 개 원래 기사 · 원의 찬양 (10) · 전망 1127

추천

출처blog.csdn.net/weixin_41746577/article/details/103956823