php中文网

Head First Java中多个线程同时取款,为什么会出现余额不足的问题?

php中文网

head first java中的线程问题

问题:

在以下这段代码中,我们创建了两个线程来分别执行ryanandmonicajob类的run方法。每个线程对bankaccount对象进行取款操作,并在取款前检查账户余额是否大于等于取款金额。然而,输出结果却令人惊讶。

代码:

立即学习“Java免费学习笔记(深入)”;

class bankaccount {

    private int balance = 100;

    public int getbalance() {
        return balance;
    }

    public void withdraw(int amount) {
        balance = balance - amount;
    }
}

public class ryanandmonicajob implements runnable {

    private bankaccount account = new bankaccount();

    public static void main(string[] args) {
        ryanandmonicajob thejob = new ryanandmonicajob();
        thread one = new thread(thejob);
        thread two = new thread(thejob);
        one.setname("ryan");
        two.setname("monica");
        one.start();
        two.start();
    }

    public void run() {
        for (int x = 0; x < 10; x++) {
            makewithdrawal(10);
            if (account.getbalance() < 0) {
                system.out.println("overdrawn!");
            }
        }
    }

    private void makewithdrawal(int amount) {
        string currentthread = thread.currentthread().getname();
        if (account.getbalance() >= amount) {
            system.out.println(currentthread + " is about to withdraw");
            try {
                system.out.println(currentthread + " is going to sleep");
                thread.sleep(500);
            } catch (interruptedexception ex) {
                ex.printstacktrace();
            }
            system.out.println(currentthread + " woke up.");
            account.withdraw(amount);
            system.out.println(currentthread + " completes the withdrawal");
        } else {
            system.out.println("sorry, not enough for " + currentthread);
        }
    }
}

输出:

ryan is about to withdraw
ryan: sorry, not enough for ryan
monica: is about to withdraw
...

问题原因:

当ryan线程执行makewithdrawal方法时,它先输出"ryan is about to withdraw",然后进入sleep状态。然而,这并不是像你想象的那样交出控制权给另一个线程。相反,在这个sleep时间内,monica线程仍然继续执行,并且已经检测到账户余额不足,所以输出"ryan: sorry, not enough for ryan"。

一旦ryan线程从sleep状态中苏醒,它继续执行makewithdrawal方法。此时,账户余额已经发生了变化,并且不再足以支持取款操作。因此,它输出"monica is about to withdraw"。

解决方法:

为了避免这种不同步,我们可以在makewithdrawal方法中使用synchronized块来确保账户对象的访问是同步的。

private void makeWithdrawal(int amount) {
    synchronized (account) {
        String currentThread = Thread.currentThread().getName();
        if (account.getBalance() >= amount) {
            System.out.println(currentThread + " is about to withdraw");
            try {
                System.out.println(currentThread + " is going to sleep");
                Thread.sleep(500);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
            System.out.println(currentThread + " woke up.");
            account.withdraw(amount);
            System.out.println(currentThread + " completes the withdrawal");
        } else {
            System.out.println("Sorry, not enough for " + currentThread);
        }
    }
}

以上就是Head First Java中多个线程同时取款,为什么会出现余额不足的问题?的详细内容,更多请关注php中文网其它相关文章!