从run方法调用synchronized方法

时间:2014-01-08 16:35:48

标签: java multithreading

我有一个帐户模型,我想同步撤销它。但即使在使方法同步并从run方法调用它之后,输出顺序仍然存在一些问题。这是我的代码。我真的不知道是什么问题。

public class Account {
private double balance;
public Account(double balance) {
    this.balance = balance;
}
public double getBalance() {
    return balance;
}
public void setBalance(double balance) {
    this.balance = balance;
}
}


public class WithdrawThread implements Runnable {
private double amount;
private Account account;

public WithdrawThread(Account account, double amount) {
    this.account = account;
    this.amount = amount;
}

public synchronized void withdraw(double amount) {

    double bal = account.getBalance();
    if (amount > account.getBalance())
        throw new IllegalArgumentException("wrong amount");
    bal -= amount;
    account.setBalance(bal);
    System.out.println(amount + " withdraw in thread number" +        Thread.currentThread().getId() + " balance is " + bal);
}

public void run() {
    withdraw(amount);
}

}

public class MainThread {
public static void main(String[] args) {
    Account account = new Account(200);
    new Thread(new WithdrawThread(account, 40)).start();
    new Thread(new WithdrawThread(account, 10)).start();
    new Thread(new WithdrawThread(account, 10)).start();
    new Thread(new WithdrawThread(account, 20)).start();
    new Thread(new WithdrawThread(account, 30)).start();
    new Thread(new WithdrawThread(account, 10)).start();
    new Thread(new WithdrawThread(account, 40)).start();
}
}

sample output

2 个答案:

答案 0 :(得分:3)

如Sotirios Delimanolis所述,synchronized方法使用来自调用它的对象的锁,即WithdrawThread实例。您想要锁定帐户...

要么撤销帐户方法,要么使用同步块。

public void withdraw(double amount) {
    double bal;
    synchronized(account) {
        bal = account.getBalance();
        if (amount > account.getBalance())
            throw new IllegalArgumentException("wrong amount");
        bal -= amount;
        account.setBalance(bal);
    }
    System.out.println(amount + " withdraw in thread number" + Thread.currentThread().getId() + " balance is " + bal);
}

答案 1 :(得分:2)

当您synchronize同步特定对象时。然后它会阻止其他人同步该对象,直到你完成。

如果您未指定对象,则会在this上进行同步。

因此,每个线程都已自动同步。

相反,您需要在方法中使用synchronized块并在公共对象上进行同步,例如正在修改的Account

public void withdraw(double amount) {
    synchronized (account) {
        double bal = account.getBalance();
        if (amount > account.getBalance())
            throw new IllegalArgumentException("wrong amount");
        bal -= amount;
        account.setBalance(bal);
        System.out.println(amount + " withdraw in thread number" +        Thread.currentThread().getId() + " balance is " + bal);
   }
}