多线程详细解析(二) 线程的共享互斥与线程的协调

线程的共享互斥

在多线程程序里,多个线程可以自由操作,当然就有可能同时操作同一实例,这种情况有时会造成不必要的问题。

假设现在要在银行取钱,确认可用余额这部分的代码应为:

if(可用余额大于等于欲提领金额){

从可用余额中减去提领金额。

}

但是,若让两个线程同时执行,可用余额可能变成负数。

假设,账户中共有1000元,现在有A和B两个线程,都要取1000元。

当线程A和B同时操作,由于时间差,可能发生线程B夹在线程A中进行操作。

当A判断可用余额大于等于欲提领金额是,返回为TRUE,但是却并未进行提领金额,这是线程B又进行判断,仍然为TRUE。

于是线程A和线程B都从余额中扣除1000元。那么余额就变成-1000元。

这个时候就需要一种机制来防止这种问题,当一个线程在操作一个实例时,不允许其他线程同时操作这一实例。

这种机制就叫做共享互斥


在JAVA中,处理线程的共享互斥时,会用到一个关键字synchronized.


当一个方法加上synchronized是,这个方法一次只能让一个线程执行。这种方法称为同步方法。

现在利用synchronized关键字来解决上面问题:

	private int money;
	private String name;
	
	public Bank(int money, String name) {
		super();
		this.money = money;
		this.name = name;
	}


	//存款
	public synchronized void deposit(int m){
		money+=m;
	}
	
	
	//取款
	public synchronized String withdraw(int m){
		if(money>=m){
			return "取款成功";
		}else{
			return "取款失败,余额不足";
		}
	}

一个线程执行deposit()方法时,那么其他线程就不能同时执行同一实体的deposit()和withdraw()方法。


线程的协调:

假设我们想更近一步,不止是有线程在执行,其他线程就乖乖等待的简单型而已,例如:

1、若该空间有空闲则写入数据,若非空闲则等候知道出现空闲为止。

2、当该空间已空出,则通知正在等候的线程。

这是根据空间是否有空闲来进行判断的线程处理。在Java中有wait,notify和notifyall三个方法来进行处理

wait:是让线程乖乖等待的方法。obj.wait();

notify、notifyAll:唤醒等候中的线程的方法。obj.notify();obj.notifyAll();

 在调用上述三个方法是,该线程必须握有欲调用线程的锁,才可以执行,否则会抛出异常。

补充说明:

notify()和notifuAll()到底使用哪一个:

notify()方法中,当正在等候的线程不止一个,规格并未说明到底调用唤醒哪一个线程,是第一个?最后一个?还是随机?

都是根据系统而定的,因此,在写程序是,程序属性最好不要写成会根据线程而有所变动。

选择notify()方法,唤醒的线程数量比较少,程序处理速度要比notifuAll()快。但是选择notify()时,若这部分处理的不好,可能会有挂掉的风险,一般来说,选择notifuAll()写出的程序代码会比notify()可靠。

除非你能确定程序员对代码的的意义和能力限度一清二楚。否则还是使用notifuAll()比较好。


posted @ 2017-03-25 13:10  Will_Don  阅读(1040)  评论(0编辑  收藏  举报