问题描述
有这样的同步功能:
private int balance;
//...
public synchronized void executeRequest(Request request) {
switch (request.getType()) {
case CREDIT:
if(balance >= request.getAmount()) {
balance -= request.getAmount();
System.out.printf(SUCCESS,request,Thread.currentThread().getName(),balance);
} else {
System.out.printf(FAILURE,balance);
}
break;
case REPAYMENT:
balance += request.getAmount();
System.out.printf(SUCCESS,balance);
break;
}
}
我需要使用 AtomicInteger 作为 balance 参数来重写它。
我无法想出如何原子地执行两个操作:
- 余额 >= request.getAmount()
- 余额 -= request.getAmount();
我尝试像这样重写 CREDIT 操作:
private void credit(int amount,String request) {
int oldValue;
int newValue;
do {
oldValue = balance.get();
newValue = oldValue - amount;
if (oldValue >= amount) {
System.out.printf(SUCCESS,balance);
} else {
System.out.printf(FAILURE,balance);
}
} while (!balance.compareAndSet(oldValue,newValue));
}
但这行不通,因为当我们再次尝试计算 oldValue >= amount
时,无法保证 !balance.compareAndSet(oldValue,newValue)
为真。
你知道如何用 AtomicInteger 重写第一个方法吗?
解决方法
我做出了这样的决定。你怎么看?
private void credit(int amount,String request) {
int oldValue;
int newValue;
while (true) {
oldValue = balance.get();
newValue = oldValue - amount;
if (oldValue >= amount && balance.compareAndSet(oldValue,newValue)) {
System.out.printf(SUCCESS,request,Thread.currentThread().getName(),newValue);
break;
} else if (oldValue < amount) {
System.out.printf(FAILURE,oldValue);
break;
}
}
}