前言
在上一篇文章中我们学到了同步方法,可以通过锁来同步多个任务的行为,从而使得一个任务不会干涉另一个任务的资源。
现在我们需要解决的问题就是线程之间如何协作,使得多个线程可以一起工作去解决某个问题。
现在的问题不是彼此之间的干涉,而是彼此之间的协调。
而wait()
,notify()
,notifyall()
就是进行线程之间的协调。
wait()、notify()、notifyall()
wait()
使我们可以等待某个条件发生变化,这个时候线程才会被唤醒。
notify()
、notifyall()
就是对wait的线程进行唤醒。
notify()
是唤醒一个线程。
notifyall()
是唤醒所有线程。但是在同一个时间也只有一个线程能获得到锁。
wait()
要求我们必须有对象的锁才能调用,并且wait()
方法会释放掉这个锁。
notify()
、notifyall()
也是同样,需要有对象的锁。
如果在没有锁的情况下就调用了这个方法,IllegalMonitorStateException
异常。
wait()
、notify()
、notifyall()
方法是Object类的一部分而不是Thread的一部分。这是很有道理的,因为wait暂停对锁对象的同步,也就是释放锁并等待消息。notify是通知想要获得锁对象资源的线程。也就是说wait()
、notify()
、notifyall()
是对资源的一种控制。
两种形式的wait()
一、接受毫秒数作为参数
在wait()
期间对象锁是释放的。
通过notify()
、notifyall()
或者时间到期可以从wait()
中恢复
二、不接受任何参数
这种wait()
在没收到notify()
、notifyall()
消息的时候将无限等待下去。
在循环中使用wait
假设有A、B两个在等待的线程,C线程生产了一个产品并notifyall()
唤醒了A、B两个线程。
假设A线程先执行了,那这时候产品是被消耗掉了的。
如果B线程没有进行条件的检查的话就会发生错误。
错失的信号,应将条件判断放入syn方法内部
如果将条件判断放在了syn方法的外部,假如我们判断完以后是需要wait的,但是这时候还没有进入syn方法,另一个线程改变了判断条件,使得线程不应该进行wait。
我们就相当于错失了信号,造成了死锁。
wait()与sleep()的区别
这个区别其实蛮大的,一个是Object的释放锁等待方法,另一个是线程的休眠方法(不会释放锁)。
只要有对wait()
有一定的认识就应该可以明确区分两个方法。