多线程编程常常会出现各种安全问题,银行取钱是一个经典的线程安全问题。
public class Account { private String accountNo; private double balance; public Account() {} public Account(String accountNo, double balance) { this.accountNo = accountNo; this.balance = balance; } public String getAccountNo() { return accountNo; } public void setAccountNo(String accountNo) { this.accountNo = accountNo; } public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } @Override public int hashCode() { return accountNo.hashCode(); } @Override public boolean equals(Object obj) { if(obj == this) return true; if(obj != null && obj.getClass() == Account.class) { Account target = (Account)obj; return target.getAccountNo().equals(accountNo); } return false; } } public class DrawThread extends Thread { private Account account; // The amount of money that client want to draw private double drawAmount; public DrawThread(String name, Account account, double drawAmount) { super(name); this.account = account; this.drawAmount = drawAmount; } @Override public void run() { if (account.getBalance() >= drawAmount) { System.out.println(getName() + " draw money:" + drawAmount); try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } account.setBalance(account.getBalance() - drawAmount); System.out.println("The blance is:" + account.getBalance()); } else { System.out.println(getName() + "The blance is not enough!"); } } } public class DrawTest { public static void main(String[] args) { Account acct = new Account("123", 10000); new DrawThread("A", acct, 8000).start(); new DrawThread("B", acct, 8000).start(); } }
上面的程序可能出现各种结果,可运行观察之。其中一个结果如下,账户被取了比余额更多的钱,这显然是不可接受的。
A draw money:8000.0 B draw money:8000.0 The blance is:2000.0 The blance is:-6000.0