在没同步前,怎么会输出取款余额800后紧接着Bank的toString余额是1100?

在没同步前,怎么会输出取款余额800后紧接着Bank的toString余额是1100?

//有一种运行结果如下:
//存款后的账户余额为:1100
//取款后的账户余额:800
//Bank [账号:1001,余额:1100]


package bank;

public class Bank {

	private String account; // 账号
	private int balance; // 账户余额

	public Bank(String account, int balance) {
		this.account = account;
		this.balance = balance;
	}

	public String getAccount() {
		return account;
	}

	public void setAccount(String account) {
		this.account = account;
	}

	public int getBalance() {
		return balance;
	}

	public void setBalance(int balance) {
		this.balance = balance;
	}

	@Override
	public String toString() {
		return "Bank [账号:" + account + ",余额:" + balance + "]";
	}

	// 存款

	public void saveAccount() {
		// 可以在不同的位置处添加sleep方法
		// 获取当前的账号余额
		int balance = getBalance();
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		// 修改余额,存100元
		balance += 100;
		// 修改账户余额
		setBalance(balance);
		// 输出存款后的账户余额
		System.out.println("存款后的账户余额为:" + balance);
	}

	// 取款
	public void drawAccout() {

		// 获得当前的账户余额
		int balance = getBalance();
		// 修改余额,取200
		balance = balance - 200;
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		// 修改账户余额
		setBalance(balance);
		System.out.println("取款后的账户余额:" + balance);
	}
}


package bank;

//存款
public class SaveAccount implements Runnable {
	Bank bank;

	public SaveAccount(Bank bank) {
		this.bank = bank;
	}

	@Override
	public void run() {
		bank.saveAccount();
	}

}


package bank;

//取款
public class DrawAccount implements Runnable {
	Bank bank;

	public DrawAccount(Bank bank) {
		this.bank = bank;
	}

	@Override
	public void run() {
		bank.drawAccout();
	}

}


package bank;

public class Test {

	public static void main(String[] args) {
		// 创建账户,给定余额1000
		Bank bank = new Bank("1001", 1000);
		// 创建线程对象
		SaveAccount sa = new SaveAccount(bank);
		DrawAccount da = new DrawAccount(bank);
		// 创建线程对象,实现Runnable的类对象作为参数传入
		Thread save = new Thread(sa);
		Thread draw = new Thread(da);
		save.start();
		draw.start();
		// 加join方法的目的是想让打印输出bank的tostiring方法最后一个输出;
		try {
			save.join();
			draw.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(bank);

	}

}


正在回答

登陆购买课程后可参与讨论,去登陆

6回答

同学你好,这里你可以这样理解,这里存款与取款都是一个线程,操作的对象没有加锁,而这两个线程是同时执行的,所以最后main方法中调用的toString方法输出的对象是随机的,可能是存款的线程中的也有可能是取款的线程中的哟,因为那是两个同时执行的线程!

所以最后输出的toString中的对象可能是取款线程中的结果,也有可能是存款线程中的结果!

如果我的回答解决了你的疑惑,请采纳。祝:学习愉快~


提问者 慕哥5118177 2019-06-10 19:30:01

//存款后的账户余额为:1100

//取款后的账户余额:800

//Bank [账号:1001,余额:1100]

我不理解这样的运行结果,请老师解惑!

提问者 慕哥5118177 2019-06-10 19:28:51

老师,你说的我明白。

但是这不能解释,为什么最后bank的toString余额还是第一步存款后的余额1100?为什么不是第二步取款后的余额800?

这里,第二步输出取款后余额800,说明余额已更新为800,而且存款和取款线程都运行完了,

第二步和第三步的余额不一样,要怎么理解?

我无法模拟程序的运行步骤,老师能具体说一下程序具体步骤吗?

好帮手慕小班 2019-06-10 10:39:16

同学你好,在没有同步前的测试方法中,创建两个线程,这两个线程同时获取到一个Bank对象,这时两个线程获取对象的内容都是编号1001,金额1000,然后线程调用各自的方法,进行金额的加或者减,所以最后线程对应的值会出现余额为800和余额为1100!

http://img1.sycdn.imooc.com//climg/5cfdc17700015aef04050082.jpg

这是因为线程并没有加锁,当第一个线程操作时,第二个线程同时进行操作,获取的是同一个对象,当操作完成后,输出的是线程对应操作完成后的值,所以会出现不同的操作值!

如果我的回答解决了你的疑惑,请采纳。祝:学习愉快~

  • 提问者 慕哥5118177 #1
    老师,你说的我明白。但是这不能解释,为什么最后bank的toString余额还是第一步存款后的余额1100?为什么不是第二步取款后的余额800?这里,第二步输出取款后余额800,说明余额已更新为800,而且存款和取款线程都运行完了,第二步和第三步的余额不一样,要怎么理解?我无法模拟程序的运行步骤,老师能具体说一下程序具体步骤吗?
    2019-06-10 19:28:24
提问者 慕哥5118177 2019-06-10 01:24:28

老师,

我举的例子中,第二步能输出取款后余额800,说明余额已更新为800,那为什么最后bank的toString余额还是第一步存款后的余额1100?为什么不是第二步取款后的余额800?

第二步和第三步的余额不一样,要怎么理解?

如果第二步和第三步显示的值一样,我是理解的。

好帮手慕小班 2019-06-09 17:39:46

同学你好,这里没有加同步,首先每个线程都获取到了而同一个对象内容

       // 创建账户,给定余额1000

        Bank bank = new Bank("1001", 1000);

都获取到了账户余额是1000元,调用取款方法,余额减去200     调用存款方法,余额加上100

这两个线程有随机性,多运行几次,就会出现不同的结果,例如

http://img1.sycdn.imooc.com//climg/5cfcd3aa000118f807630633.jpg

http://img1.sycdn.imooc.com//climg/5cfcd3c8000140f409040653.jpg

所以这里是线程随机的哦!

如果我的回答解决了你的疑惑,请采纳。祝:学习愉快~

  • 提问者 慕哥5118177 #1
    老师, 我举的例子中,第二步能输出取款后余额800,说明余额已更新为800,那为什么最后bank的toString余额还是第一步存款后的余额1100?为什么不是第二步取款后的余额800? 第二步和第三步的余额不一样,要怎么理解? 如果第二步和第三步显示的值一样,我是理解的。
    2019-06-10 01:24:55
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师