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,从而造成该线程无限期阻塞。