wait()-notify()的正确写法

0. 前言

  知道Java的开发者应该都知道其中的wait/notify。简单的说就是线程的挂起和唤醒。那么你确定知道你的wait-notify写对了吗?
本文只介绍写法和checklist,至于wait-notify的作用以及原理等不做叙述,请参考谷歌,百度或相关书籍资料。

1. 正确写法

  参考java.lang.Object的java doc,不难知道正确写法如下:

1.1. wait()正确的写法

synchronized (obj) {

         while (<条件不成立>)
             obj.wait();
 }
 
 

1.2. notify()、notifyAll()正确的写法:

synchronized (obj)  {

         修改wait()的while的条件。

         obj.notify();(或者是obj.notifyAll())。

}


2. wait/notify的checklist

2.1. 要有同步(synchronized)

没有同步则不正确。

如果有同步,需要检查同步的对象是否正确,是否是为了wait()才加的同步。

※由于wait时会放锁,所以一定要考虑好同步的对象是否正确。要考虑是否需要大锁套小锁,也就是synchronized里嵌套synchronized。

notify()、notifyAll()也要在同步块中,同步的对象与wait()对应。

 

2.2.  wait()要在while循环中

按照jdk的说明,wait()需要在while循环中。

while循环中检查条件,如果条件不成立则wait()。

(主要是为了防止线程的假醒)

 

2.3. notify前先修改while循环条件

在notify()或notifyAll()的同步块中先修改针对wait()的while循环中的条件,使while循环中的条件成立(也可能还达不到成立),然后再notify()、notifyAll()。

 

2.4. notify()或是notifyAll()与wait()是否匹配

找到wait()对应的notify()或是notifyAll()方法,没有则不正确。

另外,查看在notify()或notifyAll()中是否修改了wait()的循环等待条件。参照2.3。

如果使用的是wait(timeout),可以没有notify()或notifyAll(),详细参见2.5。

 

2.5. 是否会有假醒(spurious wakeups)

通过2的方法保证条件成立时才不继续等待。

需要特别说明的是,

wait(timeOut)也必须遵守2.2的规定;

 

如果使用的是wait(timeOut)方法,又没有notify()或是notifyAll(),

则需要看是否只是为了计时,如果是,则应该使用sleep(timeOut)方法。

由于遵守2.2,即使假醒,wait(timeOut)的条件不成立的话,还会继续wait(timeOut)。

 

2.6. notify()或notifyAll()是否会在wait()之前被调用。

看notify()或是notifyAll()是否会在wait()之前调用

        如果不会,则不需要处理;

如果会,需要检查notify()或是notifyAll()在wait()之前被调用是否是有问题。

如果没有问题,则要保证wait()之前的while循环条件的逻辑正确,保证不会一直wait()。

 

2.7.  如果不是notifyAll()需要检查notify()是否有问题。

由于调用notify(),不知道究竟哪个等待线程被唤醒,

所以一定保证wait的条件正确。

只有满足条件的线程才会继续执行,其他线程还是处于wait()状态。

 

2.8. 如果有多个线程同时在wait()一个对象时,notifyAll()时是否会有问题。

是否是预期的那个wait()的操作完成了。

例如:发送request后等待response,当有response回来的时候,检查是否是对应request的response回来时才notify()。

这种情况关键要看wait()的条件是否正确。

所以在设置wait()的条件的时候,要检查wait()的while()条件设置是否合理,

同时也要检查notify()或notifyAll()前修改wait()的while()条件是否正确。
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值