Java-wait与notify

前言

在上一篇文章中我们学到了同步方法,可以通过锁来同步多个任务的行为,从而使得一个任务不会干涉另一个任务的资源。

现在我们需要解决的问题就是线程之间如何协作,使得多个线程可以一起工作去解决某个问题。

现在的问题不是彼此之间的干涉,而是彼此之间的协调。

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()有一定的认识就应该可以明确区分两个方法。

 

打赏