我正在尝试以线程安全的方式解决将钱从一个帐户转移到另一个帐户的问题,因为这些帐户仅存在于内存中。 我能够轻松地使用CAS解决问题。但是,查看互联网上的其他解决方案,每个人似乎都坚决使用明确的锁来允许交易的原子性,但是在这种情况下,即使交易操作(即退出,然后存款不是原子质),但最终是一致的。 我正在试图了解为什么我要使用锁?最终的状态始终是一致的,没有可能的负平衡
这是我简单的实现
eventual balance consistency
然后对于帐户转移,我有一个服务类,
public class Account {
private final long id;
private final AtomicReference<BigDecimal> balance;
public Account(long id, BigDecimal balance) {
this.id = id;
this.balance = new AtomicReference<>(balance);
}
public long getId() {
return id;
}
public void withdraw(BigDecimal amount) {
BigDecimal currentBalance, newBalance;
do {
currentBalance = balance.get();
if(currentBalance.compareTo(amount) < 0) {
throw new InsufficientBalanceException("Unable to withdraw amount: " + amount +
" which is greater than existing balance: " + balance);
}
newBalance = currentBalance.subtract(amount);
} while (!balance.compareAndSet(currentBalance, newBalance));
}
public void deposit(BigDecimal amount) {
BigDecimal currentBalance, newBalance;
do {
currentBalance = balance.get();
newBalance = currentBalance.add(amount);
} while (!balance.compareAndSet(currentBalance, newBalance));
}
private static class InsufficientBalanceException extends RuntimeException {
public InsufficientBalanceException(String msg) {
super(msg);
}
}
}
现在,我试图理解在什么情况下一致性会丢失?我相信这是我们可以成为最高的表现。
在我的卑鄙看法中,您的代码包含不必要的东西(
public class AccountServiceAllowVariance {
public boolean transfer(Account source, Account destination, BigDecimal amount) {
Objects.requireNonNull(source, "``from` account cannot be null");
Objects.requireNonNull(destination, "`to` account cannot be null");
Objects.requireNonNull(amount, "`amount` cannot be null");
if(source.equals(destination)) {
throw new IllegalArgumentException("`from` & `to` accounts cannot be same");
}
if(amount.compareTo(BigDecimal.ZERO) < 0) {
throw new IllegalArgumentException("`amount` must be greater than 0");
}
source.withdraw(amount);
source.deposit(amount);
return true;
}
}
),错误的事物(while
final
通过返回布尔值,我可以无问题地处理操作。
withdraw和deposit呼叫
操作,作为参数传递的事务数量和整数值,以标识操作类型。
在这种方式中,宣布操作
同步我们控制可能的同时访问。 如果是“ 0”,我们首先检查是否有足够的余额进行撤回,如果是这样,我们继续更新thebalance值并返回True,如果没有,我们返回false
.。 如果是“ 1”。 在行countserviceallowvariance,我们添加了一个执行存款操作的
public class Account {
private final long id;
private BigDecimal balance;
public Account( long id, BigDecimal balance ) {
this.id = id;
this.balance = balance;
}
synchronized boolean operations( BigDecimal amount, int operationType ) {
if( operationType == 0 ) {
if( amount.compareTo( balance ) <= 0 ) {
balance = balance.subtract( amount );
return true;
}
return false;
}
else {
balance = balance.add( amount );
return true;
}
}
public boolean withdraw( BigDecimal amount ) {
return operations( amount, 0 );
}
public boolean deposit( BigDecimal amount ) {
return operations( amount, 1 );
}
public long getId() {
return id;
}
}
public class AccountServiceAllowVariance {
public boolean transfer( Account source, Account destination, BigDecimal amount ) {
Objects.requireNonNull( source, "``from` account cannot be null" );
Objects.requireNonNull( destination, "`to` account cannot be null" );
Objects.requireNonNull( amount, "`amount` cannot be null" );
if( source.equals( destination ) ) {
throw new IllegalArgumentException( "`from` & `to` accounts cannot be same" );
}
if( amount.compareTo( BigDecimal.ZERO ) < 0 ) {
throw new IllegalArgumentException( "`amount` must be greater than 0" );
}
if( source.withdraw( amount ) ) {
destination.deposit( amount );
return true;
}
return false;
}
void test() {
Account source = new Account( 0, BigDecimal.ONE );
Account destination = new Account( 0, BigDecimal.ZERO );
if( transfer( source, destination, BigDecimal.ONE ) ) {
System.out.println( "Yes!!" );
}
else {
System.out.println( "Nop!" );
}
}
public static void main( String[] args ) {
new AccountServiceAllowVariance().test();
}
}