数据库保证在并发情况下不会发生死锁,而且还能保证ACID
Connection conn = null;
try{
// 获取数据库连接
conn = DriverManager.getConnection();
// 设置手动提交事务
conn.setAutoCommit(false);
// 执行转账SQL
...
// 提交事务
conn.commit();
} catch (Exception e) {
// 出现异常回滚事务
conn.rollback();
}
@AllArgsConstructor
public class UnsafeAccount {
private long balance;
// 转账,存在死锁问题
public void transfer(UnsafeAccount to, long amt) {
synchronized (this) {
synchronized (to) {
if (this.balance > amt) {
this.balance -= amt;
to.balance += amt;
}
}
}
}
}
Java语言并不支持STM,可以借助第三方类库来Multiverse实现
public class Account {
// 余额
private TxnLong balance;
public Account(long balance) {
this.balance = StmUtils.newTxnLong(balance);
}
// 转账
public void transfer(Account to, int amt) {
// 原子化操作
StmUtils.atomic(() -> {
if (this.balance.get() > amt) {
this.balance.decrement(amt);
to.balance.increment(amt);
}
});
}
}