利用线程安全来模拟对银行账户取钱功能

本文通过银行取款案例展示了线程不安全导致的问题,并介绍了线程同步(synchronized)如何解决多线程并发下的数据一致性。通过对比不使用锁和使用锁后的运行结果,突出了线程安全在实际开发中的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先简单介绍一下线程安全,必须发生在多个线程并发执行,若是单个线程发生线程安全的概率低,很多初学者对线程和进程理解不是很清楚,进程可以看作一个应用程序,线程可以看作应用程序的组成部分,多线程的机制可以提高效率,但是会出现共享资源不安全的问题!而在实际开发的时候一般都是两个编程模型(同步模型--线程安全以及异步模型--线程不安全)

下面是不使用线程安全,执行会发生取出的钱与余额不对应,会多取钱,发生线程不安去

package com.java.projecttest;
/*实际开发中更重要的是线程的安全性
*了解线程不安全的条件
   多线程并发
   有共享数据
   共享数据有修改行为
*如何解决线程安全问题 线程排队执行不可并发执行
*这种机制又称线程同步机 优点:安全,缺点:效率低一些
两种编程模型
   同步模型
      线程排队执行,效率较低
   异步编程模型
     线程并发,效率高
 */
public class Projecttest08 {

	public static void main(String [] agrs) {
		//定义线程内部类
		class Mythread extends Thread{
			private Mymanni act;//账户对象
			
			public Mythread(Mymanni act) {
				super();
				this.act = act;
			}

			public void run() {
				//取款5000
				double money=10000;
				act.getruch(money);
			System.out.println("线程"+Thread.currentThread()+"对账户取款成功!余额还有"+act.getBalance());
			}
		}
		//创建卡
		Mymanni a=new Mymanni("action--1",10000);
		//模拟两个线程
		Thread t1=new Mythread(a);
		Thread t2=new Mythread(a);
		t1.setName("t1");
		t2.setName("t2");
		//启动
		t1.start();
		t2.start();
	}
}
//定义账户类
class Mymanni{
	private String  id;//卡号
	private  double balance;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public double getBalance() {
		return balance;
	}

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

	public Mymanni(String id, double balance) {
		super();
		this.id = id;
		this.balance = balance;
	}

	//取款方法
	public void getruch(double money) {
		//取款前
		double before=this.getBalance();
		//取款后
		double after=before-money;
		//更新
		this.setBalance(after);
	}
}

运行结果

分析看出,我取了10000,但是卡里的余额还有5000,而卡里只有10000,发生线程不安全,多取钱的小编就得去蹲号了

下面是使用线程安全机制(synchronized)

package com.java.projecttest;
/*线程同步机制解决线程安全问题*/
public class Projecttest08 {

	public static void main(String [] agrs) {
		//定义线程内部类
		class Mythread extends Thread{
			private Mymanni act;//账户对象
			
			public Mythread(Mymanni act) {
				super();
				this.act = act;
			}

			public void run() {
				//取款5000
				double money=5000;
				act.getruch(money);
			System.out.println("线程"+Thread.currentThread()+"取款"+money+"对账户取款成功!余额还有"+act.getBalance());
			}
		}
		//创建卡
		Mymanni a1=new Mymanni("action--1",10000);
		//模拟两个线程
		Thread t1=new Mythread(a1);
		Thread t2=new Mythread(a1);
		t1.setName("t1");
		t2.setName("t2");
		//启动
		t1.start();
		t2.start();
	}
}
//定义账户类
class Mymanni{
	private String  id;//卡号
	private  double balance;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public double getBalance() {
		return balance;
	}

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

	public Mymanni(String id, double balance) {
		super();
		this.id = id;
		this.balance = balance;
	}

	//取款方法
	public void getruch(double money) {
	   //这里的代码必须使用线程同步机制
		synchronized(this){
			//synchronized后面括号写的是线程共享的资源
			double before =this.getBalance();
			double after=before-money;
			try {
				Thread.sleep(1000*2);
			} catch (InterruptedException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}//等待时间
			this.setBalance(after);
		}
	}
}

运行结果

可以看出取钱正常,不存在多取钱,小编不用蹲号

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值