java锁机制之「wait」和「notify」

2019-11-09  本文已影响0人  乌木山

关键字

锁通信 wait notify

我们知道java线程一共有6种状态,分别是NEWRUNABLEBLOCKEDWAITINGTIMED_WATINGTERMINATED。而线程之前的状态切换,其中一个方式就是靠wait()、notify()机制实现。
wait/notify机制 类似一种生产者-消费者模型。 当一个线程在获取到资源的锁后,发现该资源不满足使用条件,就会调用wait()方法,等待该资源满足条件后再继续执行。 而notify()则类似生产者,如果资源满足条件了,则通过调用notify(),随机的唤醒一个之前等待的线程,通知其条件已满足,可以继续执行。

定义

wait() notify()是Object类中的两个本地方法。对于wait()方法,解释如下:
我们假设一个资源为object。如果一个线程调用了资源object的wait()方法,那么将会发生如下事情:

唤醒之后,线程则又变为可调度状态,然后需要同其他线程再次去竞争object资源的锁。一旦获取到锁之后,线程就会完全恢复,继续从object.wait()之后的代码开始执行。
由于我们一般是因为不满足某些条件,才会调用wait方法等待,因此在线程恢复执行后,我们总是应该再次去check一下条件是否满足。这是因为这样,我们总是在一个循环中触发wait()方法,类似:

           synchronized (obj) {
               while (<条件不满足>)
                   obj.wait(timeout);
               ... // 条件已满足,开始执行相应的业务逻辑
           }

notify方法则是用来从object的等待队列里,随机的唤醒一个线程。被唤醒的线程再去竞争获取object的锁,然后继续执行。

整个运作机制可以简单用下图来表示:


wait/notify

说明

无论是wait()还是notify(),其执行的前提条件都是:该线程首先持有资源对象object的锁。否则的话,就会抛出IllegalMonitorStateException异常。
wait(long timeout):和wait()方法类似的还有一个wait(long timeout),如果线程一直没有被唤醒,当超时时间到了,就会自动被唤醒。
notifyAll():notify()方法,也对应有一个notifyAll()方法,该方法会将等待队列里的所有线程都唤醒,唤醒后的线程行为和notify()保持一致。

事实上一个线程被唤醒的方式包括以下几种:

刚刚上文也提到了执行notify和wait,必须先获取到资源对象的锁,获取锁的方式有三种:

参考文献

https://www.jianshu.com/p/9ac697c166f3
https://www.jianshu.com/p/1dafbf42cc54

上一篇 下一篇

猜你喜欢

热点阅读