解决原生锁上的条件等待问题
满足条件执行问题
如果线程不满足继续执行的条件,不断循环,资源浪费
1 | while(!condition) { |
为了更节约,不满足条件,睡眠一段再检测,缺点是依靠间隔不能及时感知,如果缩短睡眠间隔,又会导致开销增加
1 | while(!condition) { |
wait/notify
wait(),notify(),notifyAll()是Object的基本方法,并且都是native的
wait可以无限期等待,实际上是传入过期时间0实现,wait过程中响应中断
1 | public final void wait() throws InterruptedException { |
每个对象自身monitor维护一个等待队列
- 要操控对象的前提是必须先获得锁,因此wait和notify操作都需要在同步块内使用
- 占有锁的线程无法继续进行,调用wait主动释放锁给别人,线程进入等待状态
- 多个线程都在等待,调用notify只能唤醒一个,notifyAll全部唤醒
- 由于之前释放了锁,被唤醒后需要重新获得锁才能继续,实际上notify的作用是从等待队列移动到同步队列
- 调用notify后,其他线程虽然被唤醒,但是要等到执行notify的线程退出同步块释放锁后才有机会执行
- 即使没notify线程也可能会被无原因唤醒,wait总要在循环检查内调用,以便错误唤醒时可以保持正确行为
等待逻辑
1 | synchronized(obj) { |
唤醒逻辑
1 | synchronized(obj) { |
使用同步方法也可以,默认是以当前实例作为锁
1 | public synchronized void needWait() throws InterruptedException { |
Wait-Notify为一种偏底层的机制,一般直接使用更高级的类实现等待唤醒逻辑
JDK应用
java.net.InetAddress
多线程通过host查ip,有一个去查就可以,其他等待
1 | //维护查询中的host |
查询完毕后调用,清除查询标记,通知其他线程已经查完
1 | private static void updateLookupTable(String host) { |
一分也是爱~
版权声明
This site by Linest is licensed under a Creative Commons BY-NC-ND 4.0 International License.
由Linest创作并维护的博客采用创作共用保留署名-非商业-禁止演绎4.0国际许可证。
本文永久链接:http://linest.github.io/2017/10/19/java-multithread-wait-notify/