java - Thread Safe money transfer using CAS & No Locks - Stack Overflow

I am trying to solve the much talked about problem of transferring money from one account to another in

I am trying to solve the much talked about problem of transferring money from one account to another in a thread safe manner, given that the accounts exist in memory only.

I was able to easily solve the problem with eventual balance consistency using CAS. However, looking through other solutions on the internet everyone seems to be adamant on using explicit locks to allow for atomicity of transaction but in this case even though transaction operations i.e. withdraw and then deposit are not atomic but are eventually consistent.

I am trying to understand why shall I use a lock? The eventual state is always consistent and there's no possibility of negative balances

This is my simple implementation

  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(currentBalancepareTo(amount) < 0) {
              throw new InsufficientBalanceException("Unable to withdraw amount: "   + amount +
                    " which is greater than existing balance: " + balance);
        }
        newBalance = currentBalance.subtract(amount);
      } while (!balancepareAndSet(currentBalance, newBalance));
   }

  public void deposit(BigDecimal amount) {
      BigDecimal currentBalance, newBalance;
      do {
          currentBalance = balance.get();
          newBalance = currentBalance.add(amount);
      } while (!balancepareAndSet(currentBalance, newBalance));
  }

  private static class InsufficientBalanceException extends RuntimeException {
      public InsufficientBalanceException(String msg) {
          super(msg);
      }
  }
}

and then for Accounts transfer I have a service class,

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(amountpareTo(BigDecimal.ZERO) < 0) {
          throw new IllegalArgumentException("`amount` must be greater than 0");
      }

      source.withdraw(amount);
      destination.deposit(amount);
      return true;
  }
}

Now, I am trying to understand in what case could the consistency be lost? I believe this is the most high performant we can become.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744616289a4584072.html

相关推荐

  • java - Thread Safe money transfer using CAS &amp; No Locks - Stack Overflow

    I am trying to solve the much talked about problem of transferring money from one account to another in

    2天前
    40

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信
['keyword'] : $thread['subject']; $header['description'] = $thread['description'] ? $thread['description'] : $thread['brief']; $_SESSION['fid'] = $fid; if ($ajax) { empty($conf['api_on']) and message(0, lang('closed')); $apilist['header'] = $header; $apilist['extra'] = $extra; $apilist['access'] = $access; $apilist['thread'] = well_thread_safe_info($thread); $apilist['thread_data'] = $data; $apilist['forum'] = $forum; $apilist['imagelist'] = $imagelist; $apilist['filelist'] = $thread['filelist']; $apilist['threadlist'] = $threadlist; message(0, $apilist); } else { include _include(theme_load('single_page', $fid)); } break; default: message(-1, lang('data_malformation')); break; } ?>