java中的同步概念不起作用?

问题描述 投票:1回答:3

我们在银行中有一百个帐户,有两个作为线程实现的职员,他们使用同步方法transferMoney将每1000次钱从编号为accountNumberFrom的帐户转移到帐户accountNumberTo。由于所有帐户均以余额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);
    }
}
java multithreading synchronize
3个回答
0
投票

一个问题是,同步的transferMoney方法仅使用一个帐户,因此另一个线程可能会访问帐户余额之后


0
投票

在您的示例中,synchronized仅阻止对myBank.transferMoney的所有线程调用,但不能确保在main thread上完成的所有线程,您可以像这样更新源代码:


0
投票

非常感谢您的有用答案。我修改了代码,现在它可以正常工作:

© www.soinside.com 2019 - 2024. All rights reserved.