话不多说咱们先看一段代码哈哈哈
public class A { private int checkedIdCard = 0; void handle(int idCard){ synchroinzed (A.class){ while(idCard==0){ //等你给他身份证 }; //办理 } } void pay(int moeny){ synchroinzed (A.class){ //付钱 } } } public class You { private A a; //单例工作人员A当然只会有一个 private int idCard = 0; //0 表示你没带身份证 boolean applyForPasspost(int idCard){ a.handle(idCard); a.pay(170); //在杭州办理护照是160块,再加10块邮费 } //省略带身份证的赋值方法 }
这段代码的意思就是我们去行政服务中心办护照,工作人员A来服务我们,我们需要给他我们的身份证才能办理对吧,办好之后付了钱才会生效。 因为A同一时刻只能服务一个人,所以我们给A加了个锁。但是上面代码有一点不符合我们的现实逻辑,
while(idCard==0){ //等你给他身份证 };
就是这一段代码,就是说如果你排队叫号,叫到你了你去柜台,发现你没带身份证,那正常情况下就是你得会回家拿身份证,工作人员A是不会让你占着位置等你的,而是会叫下一号。如果不叫下一号等你回家拿身份证来效率多低啊?那放在我们代码里面也是一样的! 所以如何提高效率呢?这就引入了"等待-通知"机制了! 我们改造下上面的类A
public class A { void handle(int idCard){ synchroinzed (A.class){ while(idCard==0){ //等你给他身份证 try{ wait(); }catch(Exception e){ } }; //办理 } } void pay(int moeny){ synchroinzed (A.class){ //付钱 notifyAll(); } } }
经过这个改造就符合我们的正常情况了!但你去了柜台发现你没身份证,工作人员告诉你不好意思你回去拿吧(wait)!就是让你去一边等着去,下一位! 翻译到java中就是,你这个线程来执行办理护照,但是你不满足条件所以你就一边等着(解锁了),不要阻塞着大家!这样效率就提高了很多了!然后等一个人办理好之后就是通知一下那些等待的线程,看看你们现在带身份证了没?如果带来再来排队! 咱们再深入的剖析一下这个流程
就是我们被锁的方法就会被统一包起来!所有的进出都被synchroinzed 把控了。 等待对列就是存放那些等待的想进入这个临界区的线程们,条件变量就是对应着我们上面代码的IdCard,调用了wait()就表示不满足我们的条件,所以让当前线程进去条件变量等待对列! 再调用notifyAll()表面现在条件满足了!然后那些条件对待对列中的所有线程出去到等待对列中排队了! 这个说说为什么用notifyAll()而不是notify(),因为notify()是随机唤醒一个条件变量等待对列中的线程去让他们出去继续排队!那就是有可能一些线程永远不会被通知到!那不玩完了么?所以推荐使用notifyAll(); 还有一点我们用了
while(idCard==0){ wait(); //省略try catch };
为什么加了个while循环再一次对条件进行判断呢? 因为notifyAll()的时候你的条件是满足的!但是你又出去排队了,那指不定排队轮到你的之后条件又不满足了!所以需要加个while循环!
还有如果你用的是Lock其实也是一样的意思! 所以引入了"等待-通知"机制提高了我们代码执行的效率! 希望以上内容让大家有所收获!