我是Java线程编程的新手。为了理解线程,我试图编写一个简单的程序来模拟银行帐户。我刚刚实施了提款并尝试对其进行测试。
输出的前几行如下。

T2提款前余额:1000
T2提款后余额:990
T1提款前余额:1000
T1提款后的余额:980
T2提取前的余额:980
T2提取后的余额:970
T1提款前的余额:970
T1提款后的余额:960

我的问题是,为什么输出中的第3行(T1撤回之前的余额:1000)给出的是1000而不是990。如果正确,它应该在第2行。我错过了什么吗?我的方法正确吗?

我的猜测是,试图写写入控制台的两个线程和线程T1都根本没有机会在第二行写它。

class BankAccount {

    private volatile int balance;

    public BankAccount(int b){
        balance = b;
    }

    public BankAccount(){
        balance = 0;
    }


    synchronized public int getBalance(){
        return balance;
    }

    synchronized public int withdraw(int w)
    {
        int b = getBalance();
        if(w <= b){
            balance = balance-w;
            return w;
        }
        else
            return 0;
    }
}

class WithdrawAccount implements Runnable{

    private BankAccount acc;
    private int amount;

    public WithdrawAccount(){
        acc = null;
        amount = 0;
    }

    public WithdrawAccount(BankAccount acc,int amount){
        this.acc = acc;
        this.amount = amount;
    }

    public void run() {
        int w;

        for(int i =0; i<20; i++){
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            System.out.println("Balance before "+Thread.currentThread().getName()+" withdrawl: "+acc.getBalance());
            w = acc.withdraw(amount);
            System.out.println("Balance after "+Thread.currentThread().getName()+" withdrawl: "+acc.getBalance());
            //System.out.println("amount with drawn by: "+Thread.currentThread().getName()+" "+w);

        }

    }

}

public class TestBankAccount{

    public static void main(String[] args) {

        BankAccount b = new BankAccount(1000);
        WithdrawAccount w = new WithdrawAccount(b,10);
        Thread wt1 = new Thread(w);
        wt1.setName("T1");

        Thread wt2 = new Thread(w);
        wt2.setName("T2");

        wt1.start();
        wt2.start();
    }
}

最佳答案

您没有做任何事情来同步您的run方法,因此撤回前后的printlns和撤回本身不是原子的。您正在进行线程交织。

10-08 07:13