[예시] 상태 기반 선행 조건을 갖고 있는 클래스
- BlockingQueue : 아직 비어 있는 큐에서 항목을 수 없다.
상태 의존적인 클래스를 새로! 구현하는 방법
이미 만들어져 있는 상태 의존적인 클래스를 활용해 필요한 기능을 구현한다.
자바 언어와 JDK 라이브러리에서 제공하는 저수준의 기능을 활용해 필요한 기능을 구현한다.
- 암묵적인 (instrinsic) 조건 큐
이번 장에서는 상태 종속성을 만들어 낼 수 있는 여러 가지 방법에 대해서 알아보고, 자바 플랫폼에서 제공하는 상태 종속성에 적용되는 여러 가지 규칙에 대해서도 살펴본다.
순차적으로 동작하는 프로그램은 상태 기반 선행 조건이 만족되지 않는다면 반드시 오류가 발생한다. 병렬 프로그램에서 상태 기반 선행 조건은 다른 스레드를 통해서 언제든지 변경될 수 있다.
병렬 객체의 상태 종속적인 메서드는 선행 조건이 만족되지 않았을 때 오류가 발생하는 문제를 비켜날 수도 있지만, 비켜나는 일보다는 선행 조건을 만족할 때까지 대기하는 경우가 많아진다.
자바에 내장된 조건 큐 메커니즘
→ 원하는 상태에 도달할 때까지 폴링하고 잠깐 기다리는 반복문을 사용하는 대신 조건 큐를 사용하면 된다.
반복문에서 선행 조건이 만족하지 않았을 때 락을 계속 잡고 있다면 선행 조건을 영원히 만족시키지 못한다. → 반복문 내에서 락을 다시 풀어야 다른 스레드에서 상태 변수를 변경할 수 있다.
acquire lock on object state
while (precondition does not hold) {
release lock // 선행 조건을 만족하지 못한 경우 락을 해제
wait until precondition might hold
optionally fail if interrupted or timeout expires
reacquire lock // 선행 조건을 확인하기 위해 락을 획득 혹은 대기
}
perform action
release lock
@ThreadSafe
public class GrumpyBoundedBuffer <V> extends BaseBoundedBuffer<V> {
public GrumpyBoundedBuffer() {
this(100);
}
public GrumpyBoundedBuffer(int size) {
super(size);
}
public synchronized void put(V v) throws BufferFullException {
if (isFull())
throw new BufferFullException();
doPut(v);
}
public synchronized V take() throws BufferEmptyException {
if (isEmpty())
throw new BufferEmptyException();
return doTake();
}
}