У нас есть сто счетов в банке и два клерка, реализованные в виде потоков, которые переводят каждые 1000 раз деньги со счета с номером accountNumberFrom на счет accountNumberTo, используя синхронизированный метод transferMoney. Поскольку все счета начинаются с баланса 0, а деньги, полученные с одного счета, переводятся на другой, баланс после всех транзакций должен быть равен нулю. Это верно в большинстве случаев, но не всегда. Хоть это и бывает редко, но иногда баланс после транзакций не равен 0. Что не так?
public class Clerk extends Thread {
private Bank bank;
public Clerk(String name, Bank bank) {
super(name);
this.bank=bank;
start();
}
public void run() {
for (long i=0; i<1000; i++) {
int accountNumberFrom = (int) (Math.random()*100);
int accountNumberTo = (int) (Math.random()*100);
float amount = (int) (Math.random()*1000) - 500;
bank.transferMoney(accountNumberFrom, amount);
bank.transferMoney(accountNumberTo, -amount);
}
}
}
and a class Bank
public class Bank {
Account[] account;
public Bank() {
account = new Account[100];
for (int i=0; i < account.length; i++)
account[i] = new Account();
}
public synchronized void transferMoney(int accountNumber, float amount) {
float oldBalance = account[accountNumber].getBalance();
float newBalance = oldBalance + amount;
account[accountNumber].setBalance(newBalance);
}
}
public class Banking {
public static void main (String[] args) {
Bank myBank = new Bank();
/**
* balance before transactions
*/
float sum=0;
for (int i=0; i<100; i++)
sum+=myBank.account[i].getBalance();
System.out.println("before: " + sum);
new Clerk ("Tom", myBank);
new Clerk ("Dick", myBank);
/**
* balance after transactions
*/
for (int i=0; i<100; i++)
sum+=myBank.account[i].getBalance();
System.out.println("after: " + sum);
}
}
transferMoney
может бытьsynchronized
, но ваш доступ кmyBank.account[i]
— нет. И потокиClerk
могут все еще работать в это время; вы, вероятно, хотелиjoin()
их, прежде чем суммировать общий баланс. - person Thomas   schedule 23.12.2019