如何保证 java 中 2 个顺序语句的线程安全?
How to guarantee thread safe for 2 sequential statements in java?
此模拟银行账户转账功能如下,使用 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();
}
}
看起来还可以,因为这是线程同步使用条件的常用示例,当线程中断时,锁将始终为"unlocked"。
但是如果这个线程在
之间的地方被打断
accounts[from] -= amount;//risky
和
accounts[to] += amount; //risky
那么银行总金额就不是余额了!而且我认为将 "accounts" 声明为原子数组并不能解决问题。我认为问题在于,我应该在交易中赚取“+钱”和“-钱”,要么都成功,要么应该回滚。
那么 java 并发库中有什么方便的方法可以实现这个 "transaction" 吗?或者这需要一些特殊的设计,如何实现?
非常感谢。
胎面中断不能随机发生。
如果有人调用 Thread.interrupt
它不会立即停止线程。
ThreadInterruptException
只会从声明它的方法中引发。
因此,如果您不从代码中调用任何此类方法,就没有问题。
此模拟银行账户转账功能如下,使用 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();
}
}
看起来还可以,因为这是线程同步使用条件的常用示例,当线程中断时,锁将始终为"unlocked"。
但是如果这个线程在
之间的地方被打断accounts[from] -= amount;//risky
和
accounts[to] += amount; //risky
那么银行总金额就不是余额了!而且我认为将 "accounts" 声明为原子数组并不能解决问题。我认为问题在于,我应该在交易中赚取“+钱”和“-钱”,要么都成功,要么应该回滚。
那么 java 并发库中有什么方便的方法可以实现这个 "transaction" 吗?或者这需要一些特殊的设计,如何实现?
非常感谢。
胎面中断不能随机发生。
如果有人调用 Thread.interrupt
它不会立即停止线程。
ThreadInterruptException
只会从声明它的方法中引发。
因此,如果您不从代码中调用任何此类方法,就没有问题。