나는의 첫 번째 값을 교체해야 Deque
크기가 제한을 초과하는 경우에만, 새 값으로. 나는 그것을 해결하기 위해이 코드를 썼다 :
final class Some {
final int buffer;
final Deque<Operation> operations = new ConcurrentLinkedDeque<>();
// constructors ommited;
@Override
public void register(final Operation operation) {
if (this.operations.size() == this.buffer) {
// remove the oldest operation
this.operations.removeFirst();
}
// add new operation to the tail
this.operations.addLast(operation);
}
@Override
public void apply() {
// take the fresh operation from tail and perform it
this.operations.removeLast().perform();
}
}
보시다시피, 나는 두 가지 방법, 즉 수정합니다 있습니다 Deque
. 이 코드는 멀티 스레드 환경에서 제대로 작동하는지, 의문을 가지고있다. 질문 : 그것은을 확인하는 것이 안전합니다 size()
, 수정 그 다음 작업을 수행 ConcurrentLinkedDeque
이후에? 나는 가능한 한 최소한 잠금을 갖고 싶어. 이 코드는 작동하지 않습니다 그렇다면, 나는 잠금 소개했다 다음의 사용에 아무 문제가 없다 ConcurrentLinkedDeque()
.
final class Some {
final int buffer;
final Deque<Operation> operations = new LinkedList<>();
final Lock lock = new ReentrantLock();
// constructors ommited;
@Override
public void register(final Operation operation) {
this.lock.lock();
try {
if (this.operations.size() == this.buffer) {
// remove the oldest operation
this.operations.removeFirst();
}
// add new operation to the tail
this.operations.addLast(operation);
} finally {
lock.unlock();
}
}
@Override
public void apply() {
this.lock.lock();
try {
// take the fresh operation from tail and perform it
this.operations.removeLast().perform();
} finally {
this.lock.unlock();
}
}
}
이것은 함께 대안입니다 Lock
. 유일한 방법은 내가 원하는 것을 달성하기 위해인가요? 나는 특히 동시 모음을 사용하려고 시도에 관심이 있어요.
그것이 올 때 동시 컬렉션은 스레드 안전 내부 상태. 즉, 그들은
- 내부 상태가 손상 될 것이라는 점을 여러 스레드가 읽기 / 쓰기를 동시에 걱정없이 허용
- 다른 스레드가 컬렉션을 수정하는 동안 반복 및 제거 허용
- 모든 그러나. 나는 생각
CopyOnWriteArrayList
들 'Iterator
지원하지 않는remove()
작업을
- 모든 그러나. 나는 생각
- 보증 것들과 같은 일이-전에
- 하나 개의 스레드에 의해 쓰기를 의미하는 것입니다 전에 발생 읽기 후속 스레드
그러나, 그들은은 하지 스레드 안전 에 걸쳐 외부 메소드 호출. 하나 메서드를 호출 할 때이 필요하지만, 그 잠금 시간 메서드가 반환을 출시 할 어떤 잠금 획득합니다. 당신이 조심하지 않으면 이것은으로 이어질 수 체크인 당시 행위의 경쟁 조건. 코드를 보면
if (this.operations.size() == this.buffer) {
this.operations.removeFirst();
}
this.operations.addLast(operation);
다음과 같은 상황이 발생할 수 있습니다 :
Thread-A
수표 크기 조건이 결과는false
Thread-A
새로운 추가로 이동Operation
- 전에
Thread-A
추가 할 수 있습니다Operation
,Thread-B
에서 어떤 결과를 확인 크기 조건false
뿐만 아니라를 Thread-B
새로운 추가 간다Operation
Thread-A
않는 새로운 추가Operation
- 아니, 오!
Operation
추가Thread-A
일으키는 크기 임계 값에 도달 할
- 아니, 오!
Thread-B
이미 과거if
문, 그것의 추가Operation
양단 큐가 너무 많은이 만드는Operation
들
이유는 체크인 당시 행동은 당신이를 사용하여 두 번째 예에서와 외부 동기화가 필요합니다 Lock
. 당신은 또한 사용할 수 있습니다 synchronized
온 블록을 Deque
.
귀하의 질문에 관련없는 : 당신은 전화를 Operation.perform()
계속 유지하면서 두 번째 예에 Lock
. 이것은 다른 스레드가 서로를 추가하려고 할 수 있습니다 의미 Operation
받는 Deque
동안 perform()
실행합니다. 이것은 당신과 같이 코드를 변경할 수 있습니다 바람직하지 않은 경우 :
Operation op;
lock.lock();
try {
op = deque.pollLast(); // poll won't throw exception if there is no element
} finally {
lock.unlock();
}
if (op != null) {
op.perform();
}