类介绍
概述
Condition
和Lock
在使用上的关系大概就和Object
和synchronized(xx)
块的关系相似。
-
Condition
提供了await()
,signal()
,signalAll()
方法,用于放弃锁阻塞、唤醒一个阻塞线程、唤醒所有阻塞线程。分别对应Object
中的wait()
,notify()
,notifyAll()
方法。 -
Condition
通过Lock.newContdition()
获得,从而两者之间存在多对一的关系。synchronized(xx)
块中,可以通过对象xx
来调用wait()
方法,等待xx.wait()
,也可以通过其他实例调用,Object
和synchronized
是多对一的关系。【至少用起来是】
类继承关系
实现了Condition
接口的类都可以通过Lock.newCondition()
获得并进行相应线程的阻塞或者因锁而阻塞的线程的唤醒操作。
当然,Condition
也是个普通的对象,也可以作为synchronized(xx)
或者xx.wait()
中的xx
。
源码介绍
void await() throws InterruptedException;
造成结果:
-
放弃当前线程占有的
Condition
对应的Lock
并转入阻塞 -
等待:
- 被唤醒
- 被打断
- 虚假唤醒
后结束阻塞
void awaitUninterruptibly();
造成结果:
-
放弃当前线程占有的
Condition
对应的Lock
并转入阻塞 -
等待:
- 被唤醒
- 虚假唤醒
后结束阻塞
long awaitNanos(long nanosTimeout) throws InterruptedException;
造成结果:
-
放弃当前线程占有的
Condition
对应的Lock
并转入阻塞 -
等待:
- 被唤醒
- 被打断
- 虚假唤醒
- 等待时间到达
后结束阻塞
- 入参:
- 阻塞时间,单位为纳秒
- 出参:
- 还应该等待的时间【入参-已经等待的时间】
- 正数表示提前唤醒了
- 0表示时间到后正好被唤醒
- 负数表示等待的时间比入参要长
boolean await(long time, TimeUnit unit) throws InterruptedException;
造成结果:
-
放弃当前线程占有的
Condition
对应的Lock
并转入阻塞 -
等待:
- 被唤醒
- 被打断
- 虚假唤醒
- 等待时间到达
后结束阻塞
- 入参:
long
: 阻塞时间数值TimeUnit
:数值对应的单位- 出参:
boolean
:是否提前唤醒,true
则是提前唤醒。false
则唤醒时时间已经过去。
boolean awaitUntil(Date deadline) throws InterruptedException;
造成结果:
-
放弃当前线程占有的
Condition
对应的Lock
并转入阻塞 -
等待:
- 被唤醒
- 被打断
- 虚假唤醒
- 等待时间到达
后结束阻塞
- 入参:
- 唤醒时间点
- 出参:
- 和上一个函数的规则相同,表示是否提前唤醒
void signal();
造成结果:
- 唤醒一个因为此锁而等待的线程,使其进入竞争锁状态
void signalAll();
造成结果:
- 唤醒一个因为此锁而等待的线程,使其进入竞争锁状态
扩展
虚假唤醒
介绍
虚假唤醒,英文名为spurious wakeup,是指在线程因某个条件阻塞时,我的条件并没有满足,但是线程却结束了阻塞状态。即signal()/notify()
没有被调用,但是某个因为await()/wait()
阻塞方法却被唤醒。
应对
错误用法:
if(条件不符合){
阻塞
}
正确用法:
while(条件不符合){
阻塞
}
关于wait()
时到底返回true
还是false
的问题
wait()
返回的boolean
表示是否提前唤醒。记住这句话就ok了。
网友评论