[자바 병발 노트]ReentrantLock 관련 정리

설명
우리 중의 한 사람 으로서 끊 임 없 는 학습 이 필요 합 니 다.저 는 일 을 하면 서 분석 과 정리,학습 노트 를 블 로그 로 써 서 여러분 과 함께 교류 하고 이런 방식 으로 자신의 학습 여행 을 기록 하고 싶 습 니 다.
본 고 는 학습 교류 에 만 사용 되 며,권리 침 해 는 반드시 삭제 해 야 한다.상업 목적 에 사용 되 지 않 으 니 전재 할 때 출처 를 밝 혀 주 십시오.
1. ReentrantLock
4.567917.4.567914.잠 금 을 다시 넣 을 수 있 고 Lock 과 Serializable 인 터 페 이 스 를 실현 할 수 있 습 니 다
4.567917.자바 환경 에서 4.567914.와 4.567914.모두 잠 금 을 다시 넣 을 수 있 습 니 다.
4.567917.자 물 쇠 를 다시 들 어 갈 수 있 고 재 귀 자물쇠 라 고도 합 니 다.한 스 레 드 가 대상 의 자 물 쇠 를 요청 한 후에 이 대상 의 자 물 쇠 를 다시 요청 하면 이 대상 의 자 물 쇠 를 다시 얻 을 수 있 습 니 다
4.567917.4.567914 방법 을 호출 하면 같은 스 레 드 ID 가 두 번 연속 으로 출력 됩 니 다
public void get() {
        lock.lock();
        System.out.println(Thread.currentThread().getId());
        set();
        lock.unlock();
    }

public void set() {
        lock.lock();
        System.out.println(Thread.currentThread().getId());
        lock.unlock();
}

4.567917.4.567914.구조 함수 에서 두 가지 자 물 쇠 를 제공 합 니 다.공평 한 자물쇠 와 불공평 한 자 물 쇠 를 만 듭 니 다(기본 값).
  • RentrantLock 은 세 개의 내부 클래스 Sync,NonfairSync 와 FairSync 클래스 가 있 습 니 다
  • Sync 는 AbstractQueuedSynchronizer 추상 류 를 계승 합 니 다.
  • NonfairSync(불공 정 자물쇠)는 Sync 추상 류 를 계승 합 니 다
  • FairSync(공평자물쇠)계승 Sync 추상 클래스.

  • public ReentrantLock() {
           sync = new NonfairSync();
    }
    
    public ReentrantLock(boolean fair) {
           sync = fair ? new FairSync() : new NonfairSync();
    }
    

    4.567917.공평 한 자물쇠 에 스 레 드 는 그들 이 요청 한 순서에 따라 자 물 쇠 를 얻 지만 불공평 한 자물쇠 에 서 는 새치기 가 허용 된다.
    4.567917.한 스 레 드 가 불공평 한 자 물 쇠 를 요청 할 때 요청 을 보 내 는 동시에 이 자 물 쇠 를 사용 가능 한 상태 로 바 꾸 면 이 스 레 드 는 대기 열 에 있 는 모든 대기 스 레 드 를 건 너 뛰 어 자 물 쇠 를 얻 을 수 있 습 니 다
    4.567917.불공평 한ReentrantLock새치기 행 위 를 제창 하지 않 지만 특정한 스 레 드 가 적당 한 시기 에 새치기 하 는 것 을 방지 할 수 없다

    4.567917.공평 한 자물쇠 에 다른 스 레 드 가 자 물 쇠 를 가지 고 있 거나 다른 스 레 드 가 대기 열 에서 이 자 물 쇠 를 기다 리 고 있다 면 새로 보 낸 요청 스 레 드 는 대기 열 에 들 어 갈 것 입 니 다.
    4.567917.공평 한 자물쇠 가 아 닌 특정한 스 레 드 에 잠 겨 있 을 때 새로 요청 한 스 레 드 가 대기 열 에 들 어 갈 수 있 습 니 다

    4.567917.불공 정 잠 금 성능 이 공정 잠 금 성능 보다 높 은 원인
    4.567917.걸 려 있 는 스 레 드 와 이 스 레 드 의 실제 운행 사이 에 심각 한 지연 이 존재 합 니 다
    4.567917.스 레 드 A 가 자 물 쇠 를 가지 고 있다 고 가정 하고 스 레 드 B 가 이 자 물 쇠 를 요청 합 니 다.자 물 쇠 는 A 가 가지 고 있 기 때문에 B 는 걸 릴 것 이다.A 가 자 물 쇠 를 풀 면 B 가 깨 어 나 기 때문에 B 는 다시 이 자 물 쇠 를 가 져 오 려 고 시도 합 니 다.이와 함께 스 레 드 C 도 이 자 물 쇠 를 요청 하면 C 는 B 가 완전히 깨 어 나 기 전에 이 자 물 쇠 를 얻 고 사용 하 며 방출 할 수 있 습 니 다.이렇게 하면 윈 윈 의 국면 이다.B 가 자 물 쇠 를 얻 는 시간 이 늦 어 지지 않 았 고 C 는 더욱 일찍 자 물 쇠 를 얻 었 으 며 스루풋 도 높 아 졌 다

    4.567917.자 물 쇠 를 가 진 시간 이 상대 적 으로 길 거나 자 물 쇠 를 요청 하 는 평균 시간 간격 이 길 면 공평 한 자 물 쇠 를 사용 해 야 한다.
    4.567917.이런 상황 에서 새치기 가 가 져 온 스루풋 증가(잠 금 이 사용 가능 한 상태 에 있 을 때 스 레 드 는 깨 어 나 는 과정 에 있 음)는 나타 나 지 않 을 수 있 습 니 다

    1.1 공평 자물쇠 와 불공평 자물쇠 의 실현
    공평자물쇠
  • 공평 자 물 쇠 는 스 레 드 가 자 물 쇠 를 얻 는 순 서 는 스 레 드 에 자 물 쇠 를 넣 는 순서에 따라 분배 된다 는 것 을 나타 낸다.즉,먼저 얻 은 FIFO 가 먼저 나 오 는 순서 이다.
    4.567917.모든 스 레 드 가 자 물 쇠 를 가 져 오 는 과정 은 공평 합 니 다.가장 오래 기다 리 면 가장 먼저 자 물 쇠 를 깨 워 줍 니 다

  • static final class FairSync extends Sync {
            private static final long serialVersionUID = -3000897897090466540L;
    
            final void lock() {
                acquire(1);
            }
    
            /**
             * Fair version of tryAcquire.  Don't grant access unless
             * recursive call or no waiters or is first.
             */
            protected final boolean tryAcquire(int acquires) {
                final Thread current = Thread.currentThread();
                int c = getState();
                if (c == 0) {
                    if (!hasQueuedPredecessors() &&
                        compareAndSetState(0, acquires)) {
                        setExclusiveOwnerThread(current);
                        return true;
                    }
                }
                else if (current == getExclusiveOwnerThread()) {
                    int nextc = c + acquires;
                    if (nextc < 0)
                        throw new Error("Maximum lock count exceeded");
                    setState(nextc);
                    return true;
                }
                return false;
            }
    }
    
  • 공평 자물쇠ReentrantLock방법 은 불공평 자물쇠synchronized방법 보다get()방법 이 하나 더 많아 졌 다.
  • hasQueued Predecessors 방법 은 두 결점 이 현재 스 레 드 인지 아 닌 지 를 판단 했다

  • public final boolean hasQueuedPredecessors() {
            // The correctness of this depends on head being initialized
            // before tail and on head.next being accurate if the current
            // thread is first in queue.
            Node t = tail; // Read fields in reverse initialization order
            Node h = head;
            Node s;
            return h != t &&
                ((s = h.next) == null || s.thread != Thread.currentThread());
    }
    

    불공평 자물쇠
    4.567917.공평 한 자물쇠 가 아니 라 자 물 쇠 를 얻 는 선점 체제 로 무 작위 로 자 물 쇠 를 얻 는 것 이다.공평 한 자물쇠 와 다른 것 은 먼저 자 물 쇠 를 얻 는 것 이 아니 라 이런 방식 으로 인해 일부 스 레 드 가 자 물 쇠 를 얻 지 못 할 수도 있다.결 과 는 불공평 하 다.
    4.567917.불공평 한 자 물 쇠 는 스 레 드 를 배 고 프 게 할 수 있다
    static final class NonfairSync extends Sync {
            private static final long serialVersionUID = 7316153563782823691L;
    
            /**
             * Performs lock.  Try immediate barge, backing up to normal
             * acquire on failure.
             */
            final void lock() {
                if (compareAndSetState(0, 1))
                    setExclusiveOwnerThread(Thread.currentThread());
                else
                    acquire(1);
            }
    
            protected final boolean tryAcquire(int acquires) {
                return nonfairTryAcquire(acquires);
            }
    }
    

    4.567917.공평 한 지 여 부 는 팀 에 들 어가 기 전,팀 에 들 어간 후에 순서대로 자 물 쇠 를 얻는다
    1.2 재 접속 잠 금 실현
    4.567917.스 레 드 는 이미 가지 고 있 는 자 물 쇠 를 중복 으로 얻 을 수 있 습 니 다.
    4.567917.불공평 과 공평 한 자물쇠 에서 모두 재 입 자 물 쇠 를 실현 했다
    if (current == getExclusiveOwnerThread()) {
            int nextc = c + acquires;
            if (nextc < 0)
                throw new Error("Maximum lock count exceeded");
            setState(nextc);
            return true;
    }
    

    1.3 ReentrantLock 필드 사용
    장면 1:이 조작 이 실행 중인 것 을 발견 하면 실행 하지 않 습 니 다(상태 실행)
    private ReentrantLock lock = new ReentrantLock();
    if (lock.tryLock()) {  //      lock,      false     ,         。 
             try {
    
                //  
    
             } finally {
                 lock.unlock();
             }
    
    }
    

    장면 2:이 동작 이 실행 중인 것 을 발견 하면 하나의 실행 을 기다 리 십시오(동기 화 실행,synchronized 와 유사)
    private ReentrantLock lock = new ReentrantLock(); //    false,    
    // private ReentrantLock lock = new ReentrantLock(true); //   
    try {
        lock.lock(); //         ,        ,       
    
       //  
    
    } finally {
        lock.unlock();
    }
    

    4.567917.공평 한 상황 에서 조작 은 한 팀 씩 순서대로 집행 하여 집행 순 서 를 확보한다.(줄 을 서 는 데 더 많은 시간 을 소모 할 것 이다)
  • 불공평 한 상황 에서 무질서 한 상태 에서 새치기 가 허용 되 고 JVM 은 새치기 를 어떻게 처리 하 는 지 자동 으로 계산 합 니 다.(순서 에 관심 이 없 으 면 이 속도 가 더 빨 라 집 니 다)
  • 장면 3:이 조작 이 이미 실행 되 고 있 는 것 을 발견 하면 시간 을 기다 리 고 시간 을 초과 하면 실행 하지 않 습 니 다(실행 을 기다 리 려 고 시도 합 니 다)
    try {
         if (lock.tryLock(5, TimeUnit.SECONDS)) {  //      lock,     5s,        ,   5s             false     
            try {
                //  
            } finally {
                lock.unlock();
            }
          }
    } catch (InterruptedException e) {
          e.printStackTrace(); //        (interrupt),   InterruptedException                 
    }
    

    장면 4:이 조작 이 이미 실행 중인 것 을 발견 하면 실행 을 기다 리 세 요.이 때 진행 중인 작업 을 중단 하고 즉시 자 물 쇠 를 풀 고 다음 작업 을 계속 할 수 있 습 니 다.
    try {
        lock.lockInterruptibly();
        //  
    
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        lock.unlock();
    }
    

    4.567917.이런 상황 은 주로 일부 조작 이 자원 에 대한 점용 을 취소 하 는 데 사용 된다.예 를 들 어(동기 화 되 고 있 는 작업 을 취소 하여 비정 상 작업 의 장시간 점용 으로 인 한 차단 을 방지 합 니 다)이 작업 의 비용 도 매우 많 고 일반적으로 사용 하 는 것 을 권장 하지 않 습 니 다
    장면 5:조건 판단.
    4.567917.모든 lock 은 임의의 데이터 의 Condition 대상 을 가 질 수 있 습 니 다
    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();
    lock.lock();
    try {
      while(       ) {
          condition.wait();
      }
     //     
    } finally {
        lock.unlock();
    }
    

    1.4 ReentrantLock 의 방법
    방법.
    설명 하 다.
    getHoldCount()
    현재 스 레 드 에서 이 자 물 쇠 를 가 져 오 는 횟수 를 조회 합 니 다.이 스 레 드 는 lock 방법 을 실행 하 는 횟수 입 니 다.
    getQueueLength()
    이 자 물 쇠 를 가 져 오 기 를 기다 리 는 스 레 드 추정 수 를 되 돌려 줍 니 다.예 를 들 어 10 개의 스 레 드 를 시작 하고 1 개의 스 레 드 가 자 물 쇠 를 얻 습 니 다.이때 돌아 오 는 것 은 9 입 니 다.
    getWaitQueueLength(Condition condition)
    이 자물쇠 와 관련 된 주어진 조건 을 기다 리 는 스 레 드 추정 수 를 되 돌려 줍 니 다.예 를 들 어 10 개의 스 레 드 는 같은 condition 대상 을 사용 하고 이 10 개의 스 레 드 는 condition 대상 의 await 방법 을 실 행 했 습 니 다.그러면 이 방법 을 실행 하면 10 으로 돌아 갑 니 다.
    hasWaiters(Condition condition)
    이 자물쇠 와 관련 된 주어진 조건(condition)을 기다 리 는 스 레 드 가 있 는 지 확인 합 니 다.contidon 대상 을 지정 하 는 스 레 드 가 condition.awat 방법 을 얼마나 실 행 했 는 지 확인 합 니 다.
    hasQueuedThread(Thread thread)
    주어진 스 레 드 가 이 자 물 쇠 를 가 져 오 기 를 기다 리 고 있 는 지 확인 합 니 다.
    hasQueuedThreads()
    이 자 물 쇠 를 기다 리 는 스 레 드 가 있 습 니까?
    isFair()
    이 자 물 쇠 는 공평 한 자물쇠 입 니까?
    isHeldByCurrentThread()
    현재 스 레 드 가 잠 금 을 유지 할 지 여부 입 니 다.스 레 드 의 실행 lock 방법 은 각각 false 와 true 입 니 다.
    isLock()
    이 자물쇠 에 임의의 스 레 드 가 있 는 지 여부 입 니 다.
    lockInterruptibly()
    현재 스 레 드 가 중단 되 지 않 으 면 자 물 쇠 를 가 져 옵 니 다.
    tryLock()
    자 물 쇠 를 가 져 오 려 고 시도 합 니 다.호출 할 때 만 자 물 쇠 를 스 레 드 에 차지 하지 않 고 자 물 쇠 를 가 져 옵 니 다.
    tryLock(long timeout, TimeUnit unit)
    주어진 대기 시간 동안 다른 스 레 드 에 잠 겨 있 지 않 으 면 이 자 물 쇠 를 가 져 옵 니 다.
    1.5 try Lock,lock,lock Interruptibly 의 차이
    try Lock 은 자 물 쇠 를 얻 으 면 true 로 돌아 가 고,즉시 false 로 돌아 갈 수 없습니다.
  • tryLock(long timeout,TimeUnit unit)은 시간 제한 을 증가 시 킬 수 있 습 니 다.이 시간 대 를 초과 하여 잠 금 을 얻 지 못 하면 false 로 돌아 갑 니 다

  • lock 은 자 물 쇠 를 얻 을 수 있 으 면 true 로 돌아 갑 니 다.그렇지 않 으 면 자 물 쇠 를 얻 기 를 기다 리 고 있 습 니 다.

  • 4.567917.lock 과 lock Interruptibly 는 두 스 레 드 가 각각 이 두 가지 방법 을 실행 하면 이 두 스 레 드 를 중단 하면 전 자 는 이상 을 던 지지 않 고 후 자 는 이상 을 던 집 니 다
    총화
  • ReentrantLock 은 내장 자물쇠(synchronized)와 유사 한 기능 과 메모리 의 미 를 제공 합 니 다
  • ReentrantLock 은 정 해진 잠 금 대기,중단 가능 한 잠 금 대기,공정 성과 비 블록 구 조 를 실현 하 는 잠 금 을 제공 합 니 다
  • Condition 은 스 레 드 에 대한 기다 림 과 깨 우기 등 작업 이 더욱 유연 하고 ReentrantLock 은 여러 개의 Condition 인 스 턴 스 를 가지 고 확장 할 수 있 습 니 다
  • ReentrantLock 은 표시 할 자 물 쇠 를 가 져 오고 finally 에서 자 물 쇠 를 풀 어야 합 니 다
  • JDK 1.8 이전 ReentrantLock 은 synchronized 보다 성능 이 좋 은 것 같 았 으 나 자 물 쇠 를 가 져 오 는 작업 은 특정한 스 택 프레임 과 연결 되 지 않 고 내 장 된 자 물 쇠 는 가능 합 니 다
  • 잠 금 이 내장 되 어 있 을 때 JVM 의 내 장 된 속성 때문에 앞으로 ReentrantLock 이 아 닌 synchronized 의 성능 을 향상 시 킬 수 있 습 니 다.
    4.567917.예 를 들 어 스 레 드 가 폐쇄 된 잠 금 대상 에 대해 최적화 를 제거 하고 잠 금 입 도 를 증가 시 켜 내 장 된 잠 금 의 동기 화 를 없앤다

  • 좋은 웹페이지 즐겨찾기