【发布时间】:2018-12-23 08:42:29
【问题描述】:
我需要将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 的替代方案。这是实现我想要的唯一方法吗?我对尝试使用并发集合特别感兴趣。
【问题讨论】:
-
不,非
Lock示例在多线程环境中不安全。没有外部同步,检查然后执行不是原子的。此外,除非您在运行时不允许添加Operations,否则我不会在仍持有Lock的同时调用perform()。 -
此外,
ConcurrentLinkedDeque#size()需要全面扫描,并且可能因并发添加/删除而有所不同。使用ArrayDeque和您的锁定代码可能会是最好的选择。
标签: java multithreading concurrency deque