java - 在 Java 中实现银行账户

标签 java synchronization

我是 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 和撤回本身不是原子的。您正在进行线程交错。

关于java - 在 Java 中实现银行账户,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6045242/

相关文章:

java - 重命名文件,例如 "name+index"

java - 如何调整我的图标(图像按钮)以免它们放大?

java - MySQL 列 'FullName' 不能为空

java - 没有打印语句,循环看不到其他线程更改的值

powershell - 如何使用 powershell 配置 Windows 与已知 IP 持续同步时间

java - eclipse 有没有办法一次性改变所有方法、循环、if 语句等的括号对齐方式?

java - (错误位置未知): 'basePropertyType 的重复变量声明

java - 如何使用 objectId 或 hashcode 对对象进行同步?

mysql - 同步不同数据库的 2 个表 - MySQL

asynchronous - 如何在 UWP 中创建同步新闻源