同步代码块的使用

多线程编程时,由于系统对线程的调度具有一定的随机性,所以,使用多线程同时操纵一个数据,容易出现线程安全问题。

关于线程安全问题:(经典的银行取钱案例)银行取钱的基本流程如下:

1、用户输入银行卡卡号及密码,系统进行核实。

2、用户输入取钱数目。

3、系统判断取钱数目是否大于取款数目。

4、如果大于则取款成功,小于则失败。

但是如果此操作放在并发线程里,就会引发安全问题。(两个账号同时取钱就会跳过第一个核对账号密码环节)!

首先我们创建一个账号类,用于封装用户的账号和余额,d如下:

package max.ji;

public class yinghang {
     private String no; //卡号
     private double blance;//卡里余额
	public String getNo() {
		return no;
	}
	public yinghang(String no, double blance) {
		super();
		this.no = no;
		this.blance = blance;
	}
	public void setNo(String no) {
		this.no = no;
	}
	public double getBlance() {
		return blance;
	}
	public void setBlance(double blance) {
		this.blance = blance;
	}
}

创建两个模拟取款类T1,该类继承Thread。取款金额小于等于账户总金额出款,并相应减少余额,大于提示

package max.ji;

public class T1 extends Thread{
    private yinghang acYinghang;
    private double dra;
	public T1(String name,yinghang acYinghang, double dra) {
		super(name);
		this.acYinghang = acYinghang;
		this.dra = dra;
	}
	public void run() {
		//账户余额大于取款金额时
		if (acYinghang.getBlance()>=dra) {
			System.out.println(this.getName()+"\t"+"取钱成功,此次交易金额为:"+dra+"元");
			//修改余额
			acYinghang.setBlance(acYinghang.getBlance()-dra);
			//余额
			System.out.println("卡中余额"+acYinghang.getBlance());
		}else {
			System.out.println(this.getName()+"卡里钱不够哟");
		}
	}
	//线程同步问题
	public static void main(String[] args) {
		yinghang account=new yinghang("201903300076", 1200);  //赋值卡号和卡里的金额
		new T1("张三", account, 600).start();//启动线程
		new T1("李四", account, 650).start();//启动线程
	}
}

 效果如下:

账户余额出现负数,是因为run(),方法的方法体不具备安全的功能,而程序中有两个并发线程在修改一个Account实列。两者之间抢占cpu,最终导致账户余额出现负数情况。

解决方法:java多线程中引用一个监听器,使用同步监听器的常见方法就是同步代码块。

同步代码块语法如下:

synchronized(需要锁定的对象){      //同步代码的执行体   }

作用:线程开始执行同步代码块之前,相应的对同步监视器进行锁定;

但是任何时候只有一个线程可以获得同步监视器的锁定,当该代码执行完毕后会释放对该监视器的锁定。

添加玩监视器的代码如下(将synchronized()

加入到run()中)/:

public void run() {
		//账户余额大于取款金额时
		synchronized (acYinghang) {
			if (acYinghang.getBlance()>=dra) {
				System.out.println(this.getName()+"\t"+"取钱成功,此次交易金额为:"+dra+"元");
				//修改余额
				acYinghang.setBlance(acYinghang.getBlance()-dra);
				//余额
				System.out.println("卡中余额"+acYinghang.getBlance());
			}else {
				System.out.println(this.getName()+"卡里钱不够哟");
			}
		}

	}

效果如图:(提示余额不足) 

程序在运作中通过synchronized 将acYinghang进行锁定,从而有序经历了“加锁---修改---释放”当前代码在锁定时其他线程将无法对其进行修改,该线程修改完毕后会释放资源的锁定。

总结:通过synchronized 同步代码块,可以保证并发线程中只有一个线程可以修改共享资源的代码区,保证了线程的安全。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值