我有一个帐户模型,我想同步撤销它。但即使在使方法同步并从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();
}
}
答案 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);
}
}