Java--线程安全

本文探讨了线程安全问题,通过实例说明了多线程环境下代码不连续执行导致的问题。重点讲解了同步监听器(锁)的概念,如`synchronized`关键字的使用,以及如何通过锁来确保代码块按顺序执行。以模拟银行取款为例,展示了如何应用锁机制来维护线程安全。
摘要由CSDN通过智能技术生成

一、线程不安全

之前我们介绍了线程的应用,那么在线程的应用中,会有一些意想不到的问题出现,比如我们今天提到的,线程安全。
说到线程安全,首先我们要理解多线程到底是怎么样实现的:
在下图中,我们展示了三个有三条指令的线程的一种可能执行的顺序。虽然在线程内指令是依次执行的,但是在线程之间,指令执行顺序是随机的。

多线程的执行
那么我们假设三个线程的三条指令都是一样的,且都有同一个对象a

//a.value的值初始化为9
if(a.value <10){					//Instruction1
	a.value++;						//Instruction2
	System.out.println(a.value);	//Instruction3
}

按照上图的顺序,记录一下每一步的结果
Thread2-Instruction1:a.value<10,判断可以执行if分支
Thread1-Instruction1:a.value<10,判断可以执行if分支
Thread1-Instruction2:a.value++,a.value此时为10
Thread3-Instruction1:a.value=10,判断不执行if分支
Thread2-Instruction2:a.value++,a.value此时为11
执行到这一步我们已经可以看到,a.value的值已经超出了我们希望它可所在的范围即小于等于10。a.value经过Thread1-Instruction2,已经成为了10,但是由于在Thread2-Instruction1执行判断的时候,已经通过了判断,所以可以执行Thread2-Instruction2,即便a.value现在已经不满足小于10的先决条件了,依然执行了Thread2-Instruction2

这样我们就展示了上述代码不是线程安全的。那么为了达到线程安全的目的,我们希望特定的代码是连续执行的,比如让Instruction1Instruction2,就不会出现上述的问题了,那么如何实现呢?

二、同步监听器(锁)

同步监听器,也就是锁。顾名思义,锁的作用就是将一组指令锁在一起,让这组指令在被执行的时候是连续执行的。这里我们要引入一个新的关键词synchronized,使用方法为

synchronized(Object){
//Instruction 1
//Instruction 2
//Instruction 3
//******
//Instruction n
}

通过这样的方式,我们可以使得Instruction1到n被连续的执行给不会切换到执行其他线程的指令。值得注意的是,Object是一个对象,所有线程都会使用的同一个对象,即不同的线程要用同一个锁,如果每个线程都有自己的锁,那就相当于没有锁喽。

三、模拟银行取款

我们模拟一下银行的取款,ATM机里一共有100块钱,a、b、c同时不停的每次取2块钱。
先要有钱哦。

public class Money {
	public int money = 100;
}

然后还要有人

public class User extends Thread{
	public Money money;
	public User (Money money) {
		this.money = money;
	}
	
	public void run() {
		while (money.money>0) {
			synchronized(money) {
				if (money.money>0) {
					money.money-=2;
					System.out.println(this.getName()+"取钱后还剩下"+money.money);
				}
			}
		}
	}
}

最后让银行运行起来吧

public class Bank {
	public static void main(String[] args) {
		Bank b = new Bank();
		b.draw();
	}
	
	public void draw() {
		Money m = new Money();
		User a = new User(m);
		a.setName("a");
		a.start();
		User b = new User(m);
		b.setName("b");
		b.start();
		User c = new User(m);
		c.setName("c");
		c.start();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值