공유 식 AQS
차단 식 자 물 쇠 는 같은 시간 에 한 개의 스 레 드 만 실 행 될 수 있 습 니 다.한 스 레 드 가 실 행 된 후에 다음 스 레 드 를 방출 합 니 다.공유 식 은 자 물 쇠 는 공유 할 수 있 고 같은 시간 에 여러 개의 스 레 드 가 실 행 될 수 있 습 니 다.
소스 코드 분석 을 통 해 공유 식 AQS 의 실현
Countdown Latch,Semaphore 는 모두 공유 자물쇠 에 속한다.인터넷 을 바탕 으로 많은 블 로그 들 이 Count Downlatch 를 분석 하기 때문에 저 는 여기 서 Semaphore 를 분석 해 보 겠 습 니 다.
Semaphore 의 기본 사용
public class SemaphoreTest {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(3);
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
try {
semaphore.acquire();//
System.out.println(Thread.currentThread().getName() + " " + new Date() + " ");
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
semaphore.release();//
}
}
}).start();
}
}
}
위의 코드 는 매우 간단 합 니 다.3 개의 스 레 드 를 수용 할 수 있 는 신 호 량 을 초기 화하 고 10 개의 스 레 드 를 초기 화 하 며 스 레 드 마다 인쇄 를 한 번 씩 실행 합 니 다(1 초 지연).이상 코드 실행 결과:열 려 있 는 자물쇠 에 비해 같은 시간 에 여러 스 레 드 를 동시에 실행 할 수 있 습 니 다.Semaphore 의 내부 클래스 구 조 를 보면 클래스 구조 에서 알 수 있 듯 이 Semaphore 도 공평 한 자물쇠 와 불공평 한 자물쇠 의 실현 을 지원 하고 그 자물쇠 의 실현 역시 Sync 를 통 해 AQS 를 통합 하여 이 루어 진다.
Semaphore 의 acquire 방법
public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
acquire sync 는 AQS 를 호출 하 는 acquireShared Interruptibly 방법 으로 이 루어 집 니 다.
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())//
throw new InterruptedException();
if (tryAcquireShared(arg) < 0)// , , 0 , 0 ,0 ,
doAcquireSharedInterruptibly(arg);
}
cquire Shared Interruptibly 이름 을 보면 이 방법 은 중 단 된 공유 식 으로 자 물 쇠 를 가 져 올 수 있 음 을 알 수 있 습 니 다.try Acquire Shared 도 빈 방법 으로 하위 클래스 에 남 겨 두 었 을 것 입 니 다.
protected int tryAcquireShared(int arg) {
throw new UnsupportedOperationException();
}
Semaphore 공평 자물쇠 의 try Acquire Shared 실현
protected int tryAcquireShared(int acquires) {
for (;;) {//CAS
if (hasQueuedPredecessors())// , -1,
return -1;
int available = getState();
int remaining = available - acquires;
if (remaining < 0 ||
compareAndSetState(available, remaining))// , CAS ,
return remaining;
}
}
사용 가능 한 자원 이 없 을 때 doAcquire Shared Interruptibly 방법 을 실행 합 니 다.
private void doAcquireSharedInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.SHARED);// 。
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
failed = false;
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())//
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
이때 의 데이터 구 조 는 다음 과 같다.주로 setHead and Propagate 방법 을 보 는데 이 방법 은 스 레 드 가 깨 어 난 후에 실 행 될 것 이다.
private void setHeadAndPropagate(Node node, int propagate) {
Node h = head; // Record old head for check below
setHead(node);
/*
* Try to signal next queued node if:
* Propagation was indicated by caller,
* or was recorded (as h.waitStatus either before
* or after setHead) by a previous operation
* (note: this uses sign-check of waitStatus because
* PROPAGATE status may transition to SIGNAL.)
* and
* The next node is waiting in shared mode,
* or we don't know, because it appears null
*
* The conservatism in both of these checks may cause
* unnecessary wake-ups, but only when there are multiple
* racing acquires/releases, so most need signals now or soon
* anyway.
*/
if (propagate > 0 || h == null || h.waitStatus < 0 ||
(h = head) == null || h.waitStatus < 0) {
Node s = node.next;
if (s == null || s.isShared())// ( ) ,
doReleaseShared();
}
}
이러한 깨 우기 방식 과 자 물 쇠 를 배열 하 는 것 은'공유 모델'과 구별 된다.매번 에 처음부터 하나의 스 레 드 를 깨 우 고 그 다음 에 다음 노드 의 스 레 드 를 깨 우려 고 한다.충분 한 자원 만 있 으 면 스 레 드 가 깨 어 나 고 이렇게 반복 된다.자 물 쇠 를 배열 하 는 것 처럼 한 노드 가 실 행 될 때 까지 기 다 렸 다가 다음 노드 를 깨 워 야 합 니 다.
Semaphore 의 release 방법
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {//
doReleaseShared();//
return true;
}
return false;
}
공유 잠 금 총화
4.567917.공유 자 물 쇠 는 통일 시간 에 여러 개의 스 레 드 가 실 행 될 수 있 습 니 다
4.567917.자물쇠 의 방출 과정 은 배타 적 자물쇠 에 비해 전파 성 이 있 고 한 노드 가 깨 어 나 면 처음부터 한 번 씩 깨 워 본다
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.