자바 synchronize 바 텀 실현 원리 및 최적화

먼저 synchronize 와 Lock 의 차 이 를 말 합 니 다.
둘 다 자물쇠 로 충돌 을 통제 하 는 데 사용 된다.차이 점 은 Lock 이 인터페이스 이 고 제공 하 는 기능 이 더욱 풍부 하 다 는 것 이다.이것 을 제외 하고 그들 은 다음 과 같은 차이 가 있다.
  • synchronize 는 자동 으로 자 물 쇠 를 풀 고 Lock 은 수 동 으로 풀 어야 하 며 코드 에 이상 이 생기 면 unlock 코드 가 실행 되 지 않 기 때문에 Lock 은 보통 Finally 에서 풀 리 고 synchronize 의 자 물 쇠 는 JVM 에서 자동 으로 실 행 됩 니 다
  • Lock 은 공유 자물쇠 라 는 개념 이 있 기 때문에 읽 기와 쓰기 자 물 쇠 를 설정 하여 효율 을 높 일 수 있 고 synchronize 는 할 수 없습니다.(둘 다 다시 들 어 갈 수 있다)
  • Lock 은 스 레 드 가 자 물 쇠 를 가 져 오 는 과정 에서 응답 을 중단 시 킬 수 있 지만 synchronize 는 그렇지 않 습 니 다.스 레 드 는 계속 기다 릴 것 입 니 다.lock.lockInterruptibly()방법 은 lock 처럼 잠 금 을 가 져 오 는 것 이 아니 라 중단 에 우선 응답 합 니 다
  • Lock 은 코드 블록 을 잠 그 고 synchronize 는 잠 그 는 방법 과 클래스 를 잠 글 수 있 습 니 다
  • Lock 은 스 레 드 가 자 물 쇠 를 가 져 왔 는 지 알 수 있 지만 synchronize 는
  • Lock 잠 금 은 원본 코드 가 있 는 것 에 대응 합 니 다.코드 를 볼 수 있 습 니 다.그러면 synchronize 는 JVM 차원 에서 어떻게 이 루어 졌 습 니까?다음 바이트 파일 을 보 겠 습 니 다.
    먼저 javac Test.class 로 class 파일 을 컴 파일 한 다음 javap Cc Test.class 로 바이트 파일 보기
    DEMO 를 써 서 JVM 밑바닥 이 synchronized 를 어떻게 실현 하 는 지 봅 시다.
    
    public class Test4 {
    
      private static Object LOCK = new Object();
      
      public static int main(String[] args) {
        synchronized (LOCK){
          System.out.println("Hello World");
        }
        return 1;
      }
    }
    위 코드 에 대응 하 는 바이트 코드 를 보 세 요.

    즉,자 물 쇠 는 Monitorenter 와 Monitorexit 를 통 해 이 루어 진 것 이다.이 두 바이트 코드 는 무슨 뜻 을 대표 하 는 것 입 니까?
    아래 참고 웹 페이지 에서 Monitorenter 와 Monitorexit 의 역할 을 알 수 있 습 니 다.저 는 그들의 말 을 도용 하지 않 겠 습 니 다.대체적으로 모든 대상 에 Monitorenter 모니터 가 있 습 니 다.Monitorenter 를 호출 하 는 것 은 이 대상 을 얻 으 려 고 시도 하 는 것 입 니 다.성공 적 으로 얻 으 면 값 을+1 로 줄 이 고 떠 나 면 값 을 1 로 줄 이 는 것 입 니 다.스 레 드 가 다시 들 어 오 면 값+1 은 Monitor 대상 이 다시 들 어 갈 수 있 도록 지원 한 다 는 뜻 입 니 다.
    저 는 예전 에 ReenternLock 을 분석 한 적 이 있 습 니 다.개념 은 모두 비슷 합 니 다.다만 자 물 쇠 는 자신 이 volatile int 유형의 변 수 를 유지 한 것 입 니 다.이 를 통 해 자 물 쇠 를 차지 하고 다시 들 어 가 는 것 과 같은 개념 을 표시 합 니 다.
    synchronize 가 방법 에 있다 면 위의 두 가지 명령 이 없고 대신 ACC 가 있 습 니 다.SYNCHRONIZED 수식 은 방법 에 자 물 쇠 를 채 웠 음 을 나타 낸다.이것 은 상수 탱크 에 이 식별 자 를 추가 하여 모니터 를 가 져 오기 때문에 본질 적 으로 같다.
    HotSpot 에서 잠 금 의 구체 적 인 실현 과 이에 대한 최적화:
    헤비급 잠 금:
    가장 기본 적 인 실현 방식 은 JVM 이 잠 금 을 가 져 오지 않 은 스 레 드 를 막 고 잠 금 이 풀 릴 때 이 스 레 드 를 깨 웁 니 다.차단 과 깨 우기 작업 은 운영 체제 에 의존 하여 이 루어 지기 때문에 사용자 상태 에서 커 널 상태 로 전환 해 야 하 며 비용 이 많이 든다.또한 Monitor 가 호출 한 것 은 운영 체제 밑바닥 의 상호 반 론 량(mutex)이 고 그 자체 도 사용자 상태 와 커 널 상태 로 전환 되 기 때문에 JVM 은 자전 개념 을 도입 하여 위 에서 말 한 스 레 드 전환 의 원 가 를 감소 했다.
    자동 잠 금:
    잠 금 이 다른 스 레 드 에 의 해 차지 하 는 시간 이 짧다 면 잠 금 을 가 져 오 는 다른 스 레 드 는 조금 만 기다 리 면 됩 니 다.사용자 상태 와 커 널 상태 간 의 전환 을 할 필요 가 없습니다.등의 상 태 를 자전 이 라 고 합 니 다.예 를 들 어 다음 코드:
    
    public class SpinLock {
      private AtomicReference<Thread> cas = new AtomicReference<Thread>();
      public void lock() {
        Thread current = Thread.currentThread();
        //   CAS,          
        while (!cas.compareAndSet(null, current)) {
          // DO nothing
        }
      }
      public void unlock() {
        Thread current = Thread.currentThread();
        cas.compareAndSet(current, null);
      }
    }
    자 회전 은 쓸모없는 CPU 명령 을 실행 하기 때문에 프로세서 시간 을 낭비 할 수 있 습 니 다.다른 스 레 드 에 의 해 잠 겨 있 는 시간 대가 적당 하 다 면...길 면 직접 차단 하 는 것 이 좋 습 니 다.그러면 JVM 은 자물쇠 가 차지 하 는 시간 이 길 고 짧 은 지 어떻게 압 니까?
    JVM 은 자물쇠 가 차지 하 는 시간 이 길 고 짧 은 지 모 르 기 때문에 자가 적응 자전 을 사용한다.스 레 드 가 비어 순환 하 는 횟수 를 동적 으로 조정 하 는 것 입 니 다.
    자전 은 불공평 한 자 물 쇠 를 초래 할 수 있 으 며,가장 오래 기다 리 는 라인 이 가장 먼저 자 물 쇠 를 얻 는 것 은 아니다.
    경량급 자물쇠:
    JDK 1.6 이후 가입 한 목적 은 앞의 헤비급 자 물 쇠 를 교체 하기 위 한 것 이 아니 라 실제 잠 금 경쟁 이 없 는 상황 에서 상호 배척 을 신청 하 는 것 도 줄 이 는 것 이다.잠 금 실현 의 핵심 은 대상 헤드(Markword)와 의 구조 에 있 습 니 다.대상 자체 에 모든 잠 겨 있 고 잠 겨 있 는 유형 을 나타 내 는 정보 가 있 습 니 다.다음 과 같 습 니 다.

    코드 가 동기 블록 에 들 어 갔 을 때 대상 이 잠 겨 있 지 않 은 것 을 감지 하면 표지 위 치 는 01 입 니 다.그러면 현재 스 레 드 는 자신의 스 택 프레임 에 대상 의 Markword 정 보 를 저장 하 는 구역 을 제안 하고 CAS 방식 으로 이 구역 이 대상 의 Markwork 구역 을 가리 키 도록 합 니 다.그러면 자 물 쇠 를 추가 하 더 라 도 됩 니 다.(이렇게 하면 시스템 mutex 변 수 를 가 져 오지 않 고 값 만 바 꾸 었 을 뿐 경쟁 이 있 으 면 헤비급 자물쇠 로 업그레이드 해 야 합 니 다.이렇게 하면 오히려 느 려 집 니 다)
    잠 금 추가 전 VS 잠 금 추가 후:

    편향 잠 금:
    경량급 자물쇠 보다 더 좋 습 니 다.동기 화 작업 을 모두 생략 합 니 다.설정 절 차 는 앞의 경량급 자물쇠 와 같 습 니 다.다른 것 은 표지 위치 설정 이 01,즉 편향 모드 입 니 다.
    다른 것 은 같은 스 레 드 가 두 번 째 로 들 어 온 후에 가상 컴퓨터 는 더 이상 동기 화 작업 을 하지 않 습 니 다.예 를 들 어 Mark Word 의 update 등 입 니 다.
    다른 스 레 드 가 오 면 편향 모드 가 끝나 고 표지 위 치 는 잠 겨 있 지 않 거나 잠 겨 있 지 않 습 니 다.따라서 자물쇠 가 항상 여러 스 레 드 에 접근 된다 면 편향 잠 금 을 없 애 는 것 이 좋 습 니 다.
    자물쇠 최적화 절 차 는 다음 과 같다.(주지 명 선생님 의 JVM 설명 서 에서 나 온 것)

    이 를 통 해 알 수 있 듯 이 자 물 쇠 는 점차적으로 업그레이드 되 는 과정 으로 처음부터 중량급 자물쇠 가 되 지 않 는 다.자 물 쇠 는 일반적으로 승급 만 할 수 있 고 강등 되 지 않 습 니 다.강등 후 충돌 로 인해 효율 이 떨 어 지지 않 고 또 업그레이드 해 야 합 니 다.하지만 강등 은 사실상 허용 된다(STW 때).참고 글 에 언급 된 영문 사 이 트 를 살 펴 볼 수 있다.
    다른 최 적 화 는 자물쇠 제거 와 자물쇠 조화 도 있다.
    만약 코드 가 사실 역할 영역 에 잠 금 을 넣 지 않 아 도 된다 면 자바 c 컴 파일 러 는 자동 으로 최적화 될 것 이다.
    잠 금 조 화 는 코드 가 한 코드 에 여러 번 잠 금 을 넣 으 면 JVM 에 의 해 전체 코드 세그먼트 에 잠 금 을 추가 하 는 것 을 말한다.
    (그러나 이 두 가 지 는 JVM 이 코드 에 대한 최적화 이지 synchronized 에 대한 최적화 가 아 닙 니 다.여 기 는 그냥 가 는 김 에 말씀 드 리 겠 습 니 다)
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기