【发布时间】:2014-02-24 14:44:16
【问题描述】:
我正在尝试为现有类编写一个装饰器,如果没有足够的可用资源,该类会拒绝。这是一个完全没有多线程的代码示例版本:
public interface Handler {
boolean handleTask(Task myTask); // returns true if successful, false if failure
}
public interface Task {
int getResources();
// Among other things
}
public BlockingHandler implements Handler {
private int occupied;
private final int limit;
private final Handler backingHandler;
BlockingHandler(Handler backingHandler) {
this.backingHandler = backingHandler;
}
@Override
public boolean handleTask(Task myTask) {
if(myTask.getResources() + occupied > limit) return false;
occupied += myTask.getResources();
return backingHandler.handleTask(myTask);
}
// Don't worry about this part, I'm not doing it this way, I just want the code to make sense
public void notifyResourceRelease(Task finishedTask) {
if(finishedTask.isDone()) occupied -= myTask.getResources();
}
}
问题是,这个handleTask 方法可以在多个线程上调用,而且我想要非常快(即避免synchronized)。将occupied 设为volatile 或AtomicInteger 是不够的,因为仍然可能存在竞争条件,例如:
Thread 1: call handleTask
Thread 1: call atomicOccupied.get()
Thread 2: call handleTask
Thread 1: evaluate if condition
Thread 2: call atomicOccupied.get()
不使用synchronized 是否可以做到这一点?例如,是否有一个扩展的AtomicInteger 类具有更强大的compareAndSet?
【问题讨论】:
-
听起来像是semaphore 的工作。
-
为什么不使用 ArrayBlockingQueue?该类是为这种类型的功能而构建的
-
我相信这个问题已经得到解答。 stackoverflow.com/questions/4210292/…
-
@durron597 你可以使用
if (!semaphore.tryAcquire()) throw new SomeException();。它本质上是一个 AtomicInteger,所以我会使用它而不是手动重新实现一个非常相似的逻辑。 -
@assylias 没关系,我记错了
Semaphore的工作原理,我记得.acquire()但不记得.tryAcquire()
标签: java multithreading synchronization race-condition