Этот смоделированный банковский перевод функционирует, как показано ниже, используя ReentrantLock.newCondition ():
class Bank {
private Lock bankLock = new ReentrantLock();
private Condition sufficientFunds = bankLock.newCondition();
private final double[] accounts;
public Bank(int n, double initialBalance) {
accounts = new double[n];
Arrays.fill(accounts, initialBalance);
}
public void transfer(int from, int to, double amount) throws InterruptedException {
bankLock.lock();
try {
while(accounts[from] < amount) {
sufficientFunds.await();
}
System.out.println(Thread.currentThread());
accounts[from] -= amount;//risky
// What if interrupted here ??????
accounts[to] += amount; //risky
sufficientFunds.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
bankLock.unlock();
}
}
Это выглядит нормально, поскольку это обычный пример использования условия для синхронизации потока, блокировка всегда будет "разблокирована" при прерывании потока.
Но в случае, если этот поток прерывается в местах между
accounts[from] -= amount;//risky
и
accounts[to] += amount; //risky
Тогда общая сумма в банке не будет остатками на всех! И я думаю, что объявление «учетных записей» атомным массивом не решает проблему. Я думаю, что проблема заключается в том, что я должен заработать «+ деньги» и «- деньги» внутри транзакции, либо как успешный, так и должен быть откат.
Так есть ли в java параллельной библиотеке удобный способ для выполнения этой "транзакции"? Или для этого нужен какой-то особый дизайн, и как его реализовать?
Большое спасибо.