线程同步&案例详解

【1】对于同步需要完成的两个操作

    >吧竞争访问资源标识为private

    >同步那些访问资源的代码,使用synchronized关键字来修饰方法或代码块。当synchronized方法执行完或者发生异常自动释放锁

【案例】

    >模拟银行取钱,某银行卡账号上有500,一个人拿着存折去取钱,另外一个人拿着ATM去取钱,各自取钱400,要求取钱过程中不能出现资源竞争

    >没有使用synchronized去模拟取钱的情况

public class BankDem0 {

	public static void main(String[] args) {
		Bank bank = new Bank();
		BankThread b1 = new BankThread(bank);//模拟存折取款
		b1.start();
		BankThread b2 = new BankThread(bank);//模拟ATM机取款
		b2.start();
	}

}

class BankThread extends Thread{
	private Bank bank = null;
    public BankThread(Bank bank) {
		this.bank = bank;
	}
	
	@Override
	public void run() {
		System.out.println("取款"+bank.getMoney(400));//设置取款金额为500
	}
}


class Bank{
	private int money = 500;

	public int getMoney(int number) {
		if(number < 0) {//判断取款金额是否正确
			return -1;
		}else if(money < 0) {//判断账户里面的余额是否正确
			return -2;
		}else if(number > money) {//判断取款金额是否超过存折里面的金额
			return -3;
		}else {
			try {
				Thread.sleep(1000);//休眠1秒
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
		}
		money-=number;//取钱之后存款的余额
		System.out.println("余额"+money);//输出余额
		return number;
	}
	
	
}

    >输出结果

余额-300    余额100
取款400     取款400
余额-300    余额-300

取款400     取款400    

    >结果分析

(1)   对于出现结果1,我们可以这样理解,当b1执行的时候调用run()方法,然后在调用getMoney()方法,此时符合这里面的前三个判断,则此时需要休眠1秒,而此时b2开始执行了,当b2页执行到这里的时候,b1开始进行money-=number,此时余额为100,而此时b2休眠完了,也执行到这里,故余额为100-400=-300,此时b1和b2共同执行输出语句,就会出现余额为-300

(2)  对于结果2,我们可以在(1)的基础上这样解释,当b2刚休眠的时候b1就将money的余额相减然后直接输出,也就没等到和b2一起输出,所以就会是这样的结果


 >使用synchronized去模拟取钱的情况

public class BankDem0 {

	public static void main(String[] args) {
		Bank bank = new Bank();
		BankThread b1 = new BankThread(bank);//模拟存折取款
		b1.start();
		BankThread b2 = new BankThread(bank);//模拟ATM机取款
		b2.start();
	}

}

class BankThread extends Thread{
	private Bank bank = null;
    public BankThread(Bank bank) {
		this.bank = bank;
	}
	
	@Override
	public void run() {
		System.out.println("取款"+bank.getMoney(400));//设置取款金额为500
	}
}


class Bank{
	private int money = 500;

	public synchronized int getMoney(int number) {
		if(number < 0) {//判断取款金额是否正确
			return -1;
		}else if(money < 0) {//判断账户里面的余额是否正确
			return -2;
		}else if(number > money) {//判断取款金额是否超过存折里面的金额
			return -3;
		}else {
			try {
				Thread.sleep(1000);//休眠1秒
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
		}
		money-=number;//取钱之后存款的余额
		System.out.println("余额"+money);//输出余额
		return number;
	}
	
	
}

    >输出结果

    余额100
    取款-3

    取款400

    >结果分析

    当一个线程去调用同步方法的时候,这个线程就获取了当前对象的锁,而其他线程去调用同步方法的时候只能等待,因为无法获取对象的锁,因此只能等待第一个线程释放对象的锁方可进入。

例如第一次取了400余额剩余100,第二次再去取钱因为number>money 所以返回-3



猜你喜欢

转载自blog.csdn.net/wyf2017/article/details/80375056