14. 동시 프로 그래 밍 의 ReentrantLock 공평 자물쇠 와 불공 정 자물쇠 원리 에 대한 상세 한 설명
19513 단어 병렬 프로 그래 밍
자바 언어 에는 많은 네 이 티 브 스 레 드 안전 한 데이터 구조 가 있 습 니 다. 예 를 들 어 Array BlockingQueue, CopyOn Write Array List, LinkedBlockingQueue 등 스 레 드 안전 실현 방식 은 synchronized 키워드 가 아니 라 자바 util. concurrent. locks. ReentrantLock 을 통 해 이 루어 집 니 다.ReentrantLock 의 실현 은 내부 클래스 인 FairSync (공평자물쇠) 와 NonFairSync (불공 정 자물쇠) 를 바탕 으로 이 루어 졌 다.그 접근 성 은 Thread. currentThread () 를 바탕 으로 이 루어 집 니 다. 현재 스 레 드 가 실행 시퀀스 의 자 물 쇠 를 얻 었 다 면 실행 시퀀스 후의 모든 방법 으로 이 자 물 쇠 를 얻 을 수 있 습 니 다.
1. 공평자물쇠
2. 불공 정 자물쇠
자 물 쇠 를 기다 리 는 과정 에서 새로운 스 레 드 가 자 물 쇠 를 얻 으 려 고 한다 면 자 물 쇠 를 직접 얻 을 확률 이 높다.
2. ReentrantLock 의 접근 성 분석
ReentrantLock 재 입 성 은 Thread. currentThread () 를 기반 으로 이 루어 집 니 다. 현재 스 레 드 가 잠 겨 있 으 면 이 스 레 드 의 모든 방법 으로 이 자 물 쇠 를 얻 을 수 있 습 니 다.ReentrantLock 의 잠 금 의존 도 는 NonfairSync 와 FairSync 두 가지 실현 클래스 만 있 고 그들의 잠 금 획득 방식 은 대동소이 하 다.
// else if
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
...
//
}
else if (current == getExclusiveOwnerThread()) {
// , 。 。
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
관심 을 가 져 야 할 두 가지 값 이 있 습 니 다:
//
private transient Thread exclusiveOwnerThread;
----------------- ----------------
/**
*
* 0: -
* > 0: ,
* 。
* : volatile
*/
private volatile int state;
3. ReentrantLock 자물쇠 의 실현 분석
1. 공평 자물쇠 와 불공평 자물쇠
ReentrantLock 의 공정 자물쇠 와 불공 정 자 물 쇠 는 모두 Abstract Queued Synchronizer \ # acquire 에 게 요청 하 였 습 니 다.
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
2. 공정 잠 금 FairSync
공정 자물쇠 의 실현 메커니즘 은 매번 스 레 드 가 자 물 쇠 를 선점 할 때마다 대기 열 이 있 는 지 확인 하 는 것 입 니 다. 있 으 면 현재 스 레 드 는 다음 과 같은 절 차 를 수행 합 니 다.
if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
이 중 hasQueued Predecessors 는 대기 열 이 있 는 지 확인 하 는 데 사 용 됩 니 다.
public final boolean hasQueuedPredecessors() {
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());
}
3. 불공 정 잠 금 NonfairSync
불공평 한 자 물 쇠 는 실현 할 때 무 작위 선점 을 여러 번 강조 한다.
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
공정 자물쇠 와 의 차 이 는 신 진 이 자 물 쇠 를 가 져 오 는 과정 에서 자 물 쇠 를 선점 할 수 있 는 기회 가 여러 번 있다 는 점 이다. 대기 열 에 가입 하면 공정 자물쇠 와 다 를 바 없다.
4. ReentrantLock 자물쇠 의 방출
ReentrantLock 잠 금 의 방출 은 한 단계 씩 방출 됩 니 다. 다시 들 어 갈 수 있 는 장면 에 서 는 장면 내 모든 잠 금 추가 방법 이 잠 금 을 풀 때 까지 기 다 려 야 현재 스 레 드 에 있 는 잠 금 이 풀 립 니 다. 방출 방식 은 간단 합 니 다. state 필드 에서 1 을 줄 이면 됩 니 다.
protected final boolean tryRelease(int releases) {
// releases = 1
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
5. ReentrantLock 대기 열 에 있 는 요소 의 각성
현재 잠 금 이 있 는 스 레 드 가 잠 금 을 풀 고 불공평 한 잠 금 이 스 레 드 없 이 선점 되면 스 레 드 가 깨 어 나 는 절 차 를 시작 합 니 다. tryRelease 를 통 해 잠 금 을 풀 었 습 니 다. LockSupport. unpark (s. thread) 를 호출 하고 스 레 드 차단 을 종료 합 니 다.
private void unparkSuccessor(Node node) {
//
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
Node s = node.next;
// s h Node, Null
if (s == null || s.waitStatus > 0) {
s = null;
// FIFO Cancel Node
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
//
if (s != null)
LockSupport.unpark(s.thread);
}
6. ReentrantLock 메모리 가시 성 분석
try {
lock.lock();
i ++;
} finally {
lock.unlock();
}
volatile 키워드 수식 요소 i 를 사용 하지 않 아 도 i 는 병발 문제 가 없 음 을 알 수 있 습 니 다. volatile 은 자바 언어의 키워드 입 니 다. 기능 은 수 정 된 요소 (공유 변수) 를 보장 합 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
《 나 는 병발 을 모른다 》 너 는 왜 아직도 라인 의 안전 을 모 르 니?1. 스 레 드 안전 이란 무엇 입 니까? 예: 다음 프로그램 은 라인 이 안전 합 니까? 2. 라인 안전 을 해결 하 는 일반적인 수단 자물쇠 (synchronized, volatile, Lock) 대기 열 (패키...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.