Object.wait returns normally if interrupted

David Holmes david.holmes at oracle.com
Fri Jun 27 21:23:06 UTC 2025


On 27/06/2025 10:11 pm, Pavel Rappo wrote:
> So, Object.wait() guarantees to throw InterruptedException if the
> interrupt status is set upon entrance, yes? Could this be added to
> javadoc?

It is already there:

If the current thread is interrupted by any thread *before* or while it 
is waiting, then an InterruptedException is thrown.

David
-----

> On Fri, Jun 27, 2025 at 12:59 PM David Holmes <david.holmes at oracle.com> wrote:
>>
>> 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