Object.wait returns normally if interrupted

David Holmes david.holmes at oracle.com
Fri Jun 27 11:59:08 UTC 2025


On 27/06/2025 5:58 pm, Pavel Rappo wrote:
> David,
> 
> As you correctly identified, the edge case that I mentioned is this:
> concurrent interrupt and notify [^1]. It has nothing to do with
> spurious wake-ups or virtual threads. In fact, I've seen that with
> virtual threads Object.wait behaves exactly the same way as with
> platform threads in that regard. So I cannot report any issue here.
> 
> I'm only asking about the accuracy of the javadoc contract. Say, a
> programmer uses this template from Object.wait's javadoc.
> 
>      synchronized (obj) {
>          while ( <condition does not hold and timeout not exceeded> ) {
>              long timeoutMillis = ... ; // recompute timeout values
>              int nanos = ... ;
>              obj.wait(timeoutMillis, nanos);
>          }
>          ... // Perform action appropriate to condition or timeout
>      }
> 
> Obviously, the programmer handles InterruptedException outside this
> template. Perhaps the programmer relies on that exception being thrown
> on an interrupt. So they think of this code as of interruptible.
> 
> Now, if it is generally possible -- and not just in this edge case --
> for Object.wait to return from an interrupt normally, the above code
> is effectively uninterruptible. And the programmer does not know about
> it. To fix that code, the programmer needs to additionally and
> explicitly check the interrupt status.

The wait() will throw IE on the next loop if the condition is not met. 
Otherwise the code proceeds with the knowledge the thread was notified, 
irrespective of whether the thread was also interrupted "around the same 
time".

David
-----

> In contrast, j.u.c.Condition.await, makes a special provision, which
> guarantees that if the method returns normally from an interrupt, it
> will throw an exception on the next iteration of the
> j.u.c.{Lock,Condition} analogue of the above template:
> 
>> If the current thread:
>>
>> has its interrupted status set on entry to this method;
>> or ...
>> then InterruptedException is thrown and the current thread's interrupted status is cleared.
> 
> [^1]: https://docs.oracle.com/javase/specs/jls/se24/html/jls-17.html#jls-17.2.4
> 
> On Fri, Jun 27, 2025 at 3:47 AM David Holmes <david.holmes at oracle.com> wrote:
>>
>> Hi Pavel,
>>
>> On 27/06/2025 8:23 am, Pavel Rappo wrote:
>>> Here's an interesting behaviour. A thread that has been blocked in
>>> Object.wait is interrupted. But instead of throwing an
>>> InterruptedException, Object.wait returns normally with the thread's
>>> interrupt status set.
>>
>> Do you mean it returns normally without being notified? That's allowed
>> by spec as it is just a spurious wakeup.
>>
>> That said, it shouldn't really happen in the current implementation
>> AFAIK, though with recent changes around virtual thread support it is
>> possible some new edge case has crept in. Or a bug.
>>
>> If the interrupt is racing with a notification then what you see is also
>> allowed as you can't tell which occurred first:
>>
>> "If the current thread is interrupted by any thread before or while it
>> is waiting, ...
>>
>> once notified it is no longer waiting.
>>
>>> This behaviour is not mentioned in javadoc, yet I witnessed it.
>>> Granted, I could only trigger it in an edge case described in JLS. I
>>
>> What edge case is described in current JLS?
>>
>>> wonder if the behaviour is reserved for that edge case, or it can be
>>> observed elsewhere and there is a genuine gap in javadoc. FWIW,
>>> javadoc for j.u.c.Condition documents this behaviour.
>>>
>>> Here's a practical implication of this. If some code that uses
>>> Object.wait wants to be interruptible, it must not rely on Object.wait
>>> to throw InterruptedException. It should check interrupt status or
>>> call other methods that are guaranteed to throw InterruptedException
>>> on thread interruption.
>>
>> In typical usage though if you were notified as well then responding to
>> that is generally fine and is what would happen if the notification
>> definitely occurred before the interrupt. If it was a spurious wakeup
>> then you should be re-waiting in a loop and the next wait will throw the
>> IE. So I think no real code would be adversely impacted by these edge cases.
>>
>> Cheers,
>> David
>> -----
>>
>>> -Pavel
>>



More information about the core-libs-dev mailing list