AbstractQueuedSynchronizer — FIFO 대기 큐 기반 동기화 프레임워크

AbstractQueuedSynchronizer — FIFO 대기 큐 기반 동기화 프레임워크 (AQS)

AbstractQueuedSynchronizerFIFO 대기 큐에 의존하는 블로킹 락과 관련 동기화 장치(세마포어, 이벤트 등)를 구현하기 위한 프레임워크를 제공해요. 이 클래스는 단일 원자 int 값을 상태로 나타내는 대부분의 동기화 장치에 유용한 기반이 되도록 설계됐어요.

출처: Java API Reference

본문

하위 클래스는 이 상태를 변경하는 보호된 메서드를 정의하고, 이 객체가 획득·해제되는 관점에서 그 상태가 무엇을 의미하는지 정의해야 해요. 그러면 이 클래스의 다른 메서드들이 모든 큐잉과 블로킹 메커니즘을 수행해요. 하위 클래스는 다른 상태 필드를 유지할 수 있지만, getState(), setState(int), compareAndSetState(int, int) 메서드로 조작되는 원자적 int 값만 동기화와 관련해 추적돼요.

하위 클래스는 보통 non-public 내부 헬퍼 클래스로 정의되어 그 감싸는 클래스의 동기화 속성을 구현하는 데 쓰여요. 이 클래스는 어떤 동기화 인터페이스도 구현하지 않고, 대신 acquireInterruptibly(int) 같은 메서드를 정의해서 구체적인 락과 관련 동기화 장치가 공개 메서드를 구현할 때 호출할 수 있게 해요.

이 클래스는 기본 배타(exclusive) 모드와 공유(shared) 모드를 각각 또는 둘 다 지원해요. 배타 모드로 획득되면 다른 스레드의 획득 시도는 성공할 수 없어요. 여러 스레드의 공유 모드 획득은 (반드시는 아니지만) 성공할 수 있어요. 다른 모드에서 기다리는 스레드는 같은 FIFO 큐를 공유해요. 보통 구현 하위 클래스는 이 모드 중 하나만 지원하지만, ReadWriteLock처럼 둘 다 쓰일 수 있어요.

이 클래스는 내부 큐와 조건 객체에 대한 검사(inspection)·계측(instrumentation)·모니터링 메서드를 제공해요.

사용법 (Usage)

동기화 장치의 기반으로 이 클래스를 쓰려면 상태를 검사·수정해서 다음 메서드를 오버라이드해요: tryAcquire(int), tryRelease(int), tryAcquireShared(int), tryReleaseShared(int), isHeldExclusively(). 이 메서드들은 기본적으로 UnsupportedOperationException을 던지며, 내부적으로 스레드 안전해야 하고 일반적으로 짧고 블로킹하지 않아야 해요. 이 메서드들을 정의하는 것이 이 클래스를 쓰는 유일하게 지원되는 방법이며, 다른 모든 메서드는 독립적으로 변경할 수 없으므로 final로 선언돼요.

내부 FIFO 큐를 기반으로 하지만 이 클래스는 FIFO 획득 정책을 자동으로 강제하지 않아요. 획득 시 검사가 인큐 전에 호출되므로 새로 획득하는 스레드가 다른 블로킹·큐잉된 스레드보다 앞서 나갈 수 있어요(barging). 공정 FIFO 획득 순서를 제공하려면 tryAcquirehasQueuedPredecessors()true를 반환하면 false를 반환하도록 정의하면 돼요.

기본 barging 전략이 일반적으로 처리량·확장성이 가장 높아요. 공정하거나 기아가 없다는 보장은 없지만, 먼저 큐에 있던 스레드가 나중 스레드보다 먼저 재경쟁할 수 있어요.

생성자

protected AbstractQueuedSynchronizer() — 동기화 상태가 0인 새 인스턴스를 만들어요.

상태 접근 메서드

protected final int getState() — 현재 동기화 상태 값을 반환해요. volatile 읽기 의미론을 가져요.

protected final void setState(int newState) — 동기화 상태 값을 설정해요. volatile 쓰기 의미론을 가져요.

protected final boolean compareAndSetState(int expect, int update) — 현재 상태가 예상 값과 같으면 (원자적으로) 설정해요. volatile 읽기·쓰기 의미론을 가져요.

하위 클래스가 구현하는 메서드

protected boolean tryAcquire(int arg) — 배타 모드에서 획득을 시도해요. Lock.tryLock() 구현에 쓰여요.

protected boolean tryRelease(int arg) — 배타 모드의 해제를 반영하도록 상태를 설정하려 시도해요.

protected int tryAcquireShared(int arg) — 공유 모드에서 획득을 시도해요. 실패 시 음수, 성공 시 0 또는 양수를 반환해요.

protected boolean tryReleaseShared(int arg) — 공유 모드의 해제를 반영하도록 상태를 설정하려 시도해요.

protected boolean isHeldExclusively() — 현재 스레드에 대해 동기화가 배타적으로 유지되면 true를 반환해요.

배타 모드 메서드

final void acquire(int arg) — 인터럽트를 무시하고 배타 모드로 획득해요. Lock.lock() 구현에 쓰여요.

final void acquireInterruptibly(int arg) — 인터럽트되면 중단하고 배타 모드로 획득해요. Lock.lockInterruptibly()에 쓰여요.

final boolean tryAcquireNanos(int arg, long nanosTimeout) — 시간 초과 시 실패, 인터럽트 시 중단하며 배타 모드로 획득을 시도해요. Lock.tryLock(long, TimeUnit)에 쓰여요.

final boolean release(int arg)tryRelease가 true면 스레드를 블록 해제하며 배타 모드로 해제해요. Lock.unlock()에 쓰여요.

공유 모드 메서드

final void acquireShared(int arg) — 인터럽트를 무시하고 공유 모드로 획득해요.

final void acquireSharedInterruptibly(int arg) — 인터럽트되면 중단하며 공유 모드로 획득해요.

final boolean tryAcquireSharedNanos(int arg, long nanosTimeout) — 시간 초과 시 실패, 인터럽트 시 중단하며 공유 모드로 획득을 시도해요.

final boolean releaseShared(int arg) — 공유 모드로 해제해요.

큐 검사·계측 메서드

final boolean hasQueuedThreads() — 획득을 기다리는 스레드가 있는지 조회해요.

final boolean hasContended() — 경쟁이 있었는지 조회해요. 상수 시간에 반환돼요.

final Thread getFirstQueuedThread() — 큐의 첫 스레드를 반환하거나 비어 있으면 null을 반환해요.

final boolean isQueued(Thread thread) — 주어진 스레드가 큐에 있는지 반환해요.

final boolean hasQueuedPredecessors() — 현재 스레드보다 오래 기다린 스레드가 있는지 조회해요. 공정 동기화 장치가 barging을 피하는 데 쓰여요.

final int getQueueLength() — 획득을 기다리는 스레드 수의 추정치를 반환해요.

final Collection<Thread> getQueuedThreads() / getExclusiveQueuedThreads() / getSharedQueuedThreads() — 큐에 있는 스레드 컬렉션을 반환해요.

String toString() — 이 동기화 장치와 상태를 식별하는 문자열을 반환해요.

Condition 메서드

final boolean owns(ConditionObject condition) — 주어진 ConditionObject가 이 동기화 장치를 락으로 쓰는지 조회해요.

final boolean hasWaiters(ConditionObject condition) — 주어진 condition에서 기다리는 스레드가 있는지 조회해요.

final int getWaitQueueLength(ConditionObject condition) — 주어진 condition에서 기다리는 스레드 수의 추정치를 반환해요.

final Collection<Thread> getWaitingThreads(ConditionObject condition) — 주어진 condition에서 기다리는 스레드 컬렉션을 반환해요.

더 알아보기 (Learn more)