java.util.concurrent.locks.Condition awaitUninterruptibly()
java.util.concurrent.locks.Condition awaitUninterruptibly()
当我阅读 java.util.concurrent.locks.Condition
API 文档时,
我看到了:
When waiting upon a Condition, a "spurious wakeup" is permitted to
occur, in general, as a concession to the underlying platform
semantics. This has little practical impact on most application
programs as a Condition should always be waited upon in a loop,
testing the state predicate that is being waited for. An
implementation is free to remove the possibility of spurious wakeups
but it is recommended that applications programmers always assume that
they can occur and so always wait in a loop
而 awaitUninterruptibly() 表示:
If the current thread's interrupted status is set when it enters this
method, or it is interrupted while waiting, it will continue to wait
until signalled. When it finally returns from this method its
interrupted status will still be set
那么,这是否意味着 我们不需要在循环中调用 awaitUninterruptibly()? 请澄清。提前致谢。
来自代码:
public final void awaitUninterruptibly() {
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
boolean interrupted = false;
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
if (Thread.interrupted()) interrupted = true;
}
if (acquireQueued(node, savedState) || interrupted) selfInterrupt();
}
所以等待是在一个循环中完成的,这将消除在这个函数之外循环的需要。
但是请记住,这也意味着 Thread.interrupt()
不会执行任何操作,这可能会导致代码的某些锁定,即关机期间。
specification is pretty clear:
void awaitUninterruptibly()
Causes the current thread to wait until it is signalled.
The lock associated with this condition is atomically released and the current thread becomes disabled for thread scheduling purposes and lies dormant until one of three things happens:
- Some other thread invokes the
signal()
method for this Condition and the current thread happens to be chosen as the thread to be awakened; or
- Some other thread invokes the
signalAll()
method for this Condition; or
- A "spurious wakeup" occurs.
因此,中断不在可能的唤醒条件列表中,但虚假唤醒在。不要让你通过查看一段特定的实现代码来指导。您的应用程序最终运行的实现可能完全不同。
此外,Condition
是一个 interface
,即使在一个运行时环境中也可能有不同的实现。 甚至没有具体说明 class 此代码来自哪个。
您必须使用 awaitUninterruptibly()
的常规循环执行等待操作。
考虑以下几点:
- 信号和等待之间没有1:1映射,
- 因此您可能会错过一个或多个在您的线程唤醒之前发生的信号
- 更糟糕的是,信号不会被记住,因此当它们在另一个线程开始等待之前发生时会丢失
- 因此在决定等待
之前,您必须预先检查所需的条件状态
- 这意味着一个信号可能会唤醒一个线程,但另一个线程会由于成功的预检查而消耗该状态,因此唤醒的线程必须重新检查所需的条件状态
因此,即使没有虚假唤醒,也需要一个在等待前进行预检查并在唤醒后重新检查的循环。
当我阅读 java.util.concurrent.locks.Condition
API 文档时,
我看到了:
When waiting upon a Condition, a "spurious wakeup" is permitted to occur, in general, as a concession to the underlying platform semantics. This has little practical impact on most application programs as a Condition should always be waited upon in a loop, testing the state predicate that is being waited for. An implementation is free to remove the possibility of spurious wakeups but it is recommended that applications programmers always assume that they can occur and so always wait in a loop
而 awaitUninterruptibly() 表示:
If the current thread's interrupted status is set when it enters this method, or it is interrupted while waiting, it will continue to wait until signalled. When it finally returns from this method its interrupted status will still be set
那么,这是否意味着 我们不需要在循环中调用 awaitUninterruptibly()? 请澄清。提前致谢。
来自代码:
public final void awaitUninterruptibly() {
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
boolean interrupted = false;
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
if (Thread.interrupted()) interrupted = true;
}
if (acquireQueued(node, savedState) || interrupted) selfInterrupt();
}
所以等待是在一个循环中完成的,这将消除在这个函数之外循环的需要。
但是请记住,这也意味着 Thread.interrupt()
不会执行任何操作,这可能会导致代码的某些锁定,即关机期间。
specification is pretty clear:
void awaitUninterruptibly()
Causes the current thread to wait until it is signalled. The lock associated with this condition is atomically released and the current thread becomes disabled for thread scheduling purposes and lies dormant until one of three things happens:
- Some other thread invokes the
signal()
method for this Condition and the current thread happens to be chosen as the thread to be awakened; or- Some other thread invokes the
signalAll()
method for this Condition; or- A "spurious wakeup" occurs.
因此,中断不在可能的唤醒条件列表中,但虚假唤醒在。不要让你通过查看一段特定的实现代码来指导。您的应用程序最终运行的实现可能完全不同。
此外,Condition
是一个 interface
,即使在一个运行时环境中也可能有不同的实现。
您必须使用 awaitUninterruptibly()
的常规循环执行等待操作。
考虑以下几点:
- 信号和等待之间没有1:1映射,
- 因此您可能会错过一个或多个在您的线程唤醒之前发生的信号
- 更糟糕的是,信号不会被记住,因此当它们在另一个线程开始等待之前发生时会丢失
- 因此在决定等待 之前,您必须预先检查所需的条件状态
- 这意味着一个信号可能会唤醒一个线程,但另一个线程会由于成功的预检查而消耗该状态,因此唤醒的线程必须重新检查所需的条件状态
因此,即使没有虚假唤醒,也需要一个在等待前进行预检查并在唤醒后重新检查的循环。