Java中的等待/唤醒机制
Java中实现等待唤醒机制共有三种方法:
- Java1.5之前,使用
synchronized配合wait与notify实现等待唤醒 - Java1.5及之后,由于并发工具包的加入,我们可以用lock、lock中的Condition对象的
await,signal实现等待唤醒 LockSupport类中的静态方法park、unpark。
前两种方法的缺点:
- 都需要配合锁来使用,否则会报异常
IllegalMonitorStateException - 若先
notify、后wait,则等待的线程会无限期等待
LockSupport的优点:
- 无需配合锁来使用,其底层使用了
Unsafe类,通过设置凭证(permit)来实现,permit初始为0,unpark会使permit数量加一(最多为1),因此重复调用unpark的效果与调用一次相同;park方法会使permit数量减一,多次调用可能会造成阻塞。 - 若先
unpark后park,则park不会阻塞线程
为什么等待通知要配合锁来使用?
如果没有锁的加入,可能会由于线程调度导致wait的线程错过notify,从而造成该线程无限期阻塞。