账户之间的多线程银行转账

时间:2015-07-10 14:30:29

标签: java multithreading synchronized

我编写了以下代码来实现正确行为的金额转移方案。即使在每个方法上添加同步后,我仍然会在运行程序一段时间后看到“系统不一致”错误。我不知道为什么我会这样做。感谢您的任何帮助。

我编写了以下代码来实现正确行为的金额转移方案。即使在每个方法上添加同步后,我仍然会在运行程序一段时间后看到“系统不一致”错误。我不知道为什么我会这样做。感谢您的任何帮助。

包并发;

    public class MoneyTransfer {

        static void makeTransfer(Account fromAccount, Account toAccount, long amount) {

            synchronized(MoneyTransfer.class) {
                fromAccount.withdraw(amount);
                toAccount.deposit(amount);
            }
        }

        public static void main(String a[]) {

            Account accA = new Account("a", 1000000);
            Account accB = new Account("b", 1000000);

            Thread t1 = new Thread(new MoneyTransferTask(100, accA, accB), "t1");
            Thread t2 = new Thread(new MoneyTransferTask(100, accA, accB), "t2");
            Thread t3 = new Thread(new MoneyTransferTask(100, accA, accB), "t3");
            Thread t4 = new Thread(new MoneyTransferTask(100, accA, accB), "t4");
            Thread t5 = new Thread(new MoneyTransferTask(100, accA, accB), "t5");
            Thread t11 = new Thread(new MoneyTransferTask(100, accA, accB), "t11");
            Thread t12 = new Thread(new MoneyTransferTask(100, accA, accB), "t12");
            Thread t13 = new Thread(new MoneyTransferTask(100, accA, accB), "t13");
            Thread t14 = new Thread(new MoneyTransferTask(100, accA, accB), "t14");
            Thread t15 = new Thread(new MoneyTransferTask(100, accA, accB), "t15");

            Thread t6 = new Thread(new MoneyTransferTask(100, accB, accA), "t6");
            Thread t7 = new Thread(new MoneyTransferTask(100, accB, accA), "t7");
            Thread t8 = new Thread(new MoneyTransferTask(100, accB, accA), "t8");
            Thread t9 = new Thread(new MoneyTransferTask(100, accB, accA), "t9");
            Thread t10 = new Thread(new MoneyTransferTask(100, accB, accA), "t10");

            Thread t = new Thread(new PrintBalancesTask(accA, accB), "t");

            t.start();
            t1.start();
            t2.start();
            t3.start();
            t4.start();
            t5.start();
            t6.start();
            t7.start();
            t8.start();
            t9.start();
            t10.start();
            t11.start();
            t12.start();
            t13.start();
            t14.start();
            t15.start();
        }
    }

    class MoneyTransferTask implements Runnable {

        int amount;
        Account fromAccount;
        Account toAccount;

        public MoneyTransferTask(int amount, Account fromAccount, Account toAccount) {
            this.amount = amount;
            this.fromAccount = fromAccount;
            this.toAccount = toAccount;
        }

        public void run() {
            while(true) {
                MoneyTransfer.makeTransfer(fromAccount, toAccount, amount);
                try {
                    Thread.sleep(100);
                }catch(InterruptedException ie) {
                    System.out.println("Thread " + Thread.currentThread().getName() + " interrupted");
                }
            }
        }
    }

    class PrintBalancesTask implements Runnable {

        Account accA;
        Account accB;

        public PrintBalancesTask(Account accA, Account accB) {
            this.accA = accA;
            this.accB = accB;
        }

        public void run() {
            while(true) {

                System.out.println("AccA Balance " + accA.getBalance());
                System.out.println("AccB Balance " + accB.getBalance());

                if(accA.getBalance() + accB.getBalance() != 2000000) {

                    System.out.println("AccA Balance " + accA.getBalance());
                    System.out.println("AccB Balance " + accB.getBalance());
                    throw new IllegalStateException("System inconsistent");
                }

                try {
                    Thread.sleep(5);
                }catch(InterruptedException ie) {
                    System.out.println("Thread " + Thread.currentThread().getName() + " interrupted");
                }
            }
        }

    }

    class Account {
        String accountId;
        long balance;

        Account(String accountId, long balance) {
            this.accountId = accountId;
            this.balance = balance;
        }

        synchronized long getBalance() {
            return balance;
        }

        synchronized void  withdraw(long amount) {
            balance = balance - amount;
        }

        synchronized void deposit(long amount) {
            balance = balance + amount;
        }
    }

1 个答案:

答案 0 :(得分:1)

您的代码应该可以正常运行,问题出在您的检查器上:

if(accA.getBalance() + accB.getBalance() != 2000000) {

可能会在某次转移之前执行accA.getBalance(),而在转移之后会执行accB.getBalance()

尝试在那里添加synchronized(MoneyTransfer.class)

synchronized(MoneyTransfer.class) {
    if(accA.getBalance() + accB.getBalance() != 2000000) {
}