RFR: In rare cases, the unlock() on join() might fail, causing an IllegalMonitorStateException

David Holmes david.holmes at oracle.com
Thu Feb 25 22:01:27 UTC 2021


On 26/02/2021 6:14 am, Alex Otenko wrote:
> I wonder what reasons may be to want to transition from synchronized/wait
> to Condition/await

Because synchronized/wait, with Loom, causes carrier thread to be 
pinned, which is undesirable in general. So Loom has been converting 
such uses.

Cheers,
David

> Alex
> 
> On Thu, 25 Feb 2021, 14:32 Dr Heinz M. Kabutz, <heinz at javaspecialists.eu>
> wrote:
> 
>> On 2021/02/25 14:07, Alan Bateman wrote:
>>> On Thu, 25 Feb 2021 11:10:41 GMT, kabutz <github.com+
>> 332398+kabutz at openjdk.org> wrote:
>>>
>>>> Unlike synchronized/wait, the Condition.await() method does not
>> necessarily reacquire the lock on exit, for example if the thread is
>> stopped or if CTRL+C is caused in jshell. In that case we would enter the
>> finally block without the lock held and unlocking would cause an
>> IllegalMonitorStateException.
>>>>
>>>> For example, run the following code from jshell and then press CTRL+C:
>>>>
>>>> Object monitor = new Object();
>>>> for (int i = 0; i < 10_000; i++) {
>>>>     Thread.startVirtualThread(() -> {
>>>>       synchronized (monitor) {
>>>>         try {
>>>>           monitor.wait();
>>>>         } catch (InterruptedException ignore) {}
>>>>       }
>>>>     });
>>>> }
>>>> Thread.startVirtualThread(() -> System.out.println("done")).join();
>>>>
>>>> Output is:
>>>>
>>>> |  Exception java.lang.IllegalMonitorStateException
>>>> |        at ReentrantLock$Sync.tryRelease (ReentrantLock.java:175)
>>>> |        at AbstractQueuedSynchronizer.release
>> (AbstractQueuedSynchronizer.java:1007)
>>>> |        at ReentrantLock.unlock (ReentrantLock.java:494)
>>>> |        at VirtualThread.joinNanos (VirtualThread.java:635)
>>>> |        at Thread.join (Thread.java:2281)
>>>> |        at Thread.join (Thread.java:2366)
>>>> |        at (#3:1)
>>> I'm in two minds about point fixes to improve robustness with
>> Thread.stop. In this case, there are other usages of Condition::await,
>> including some of the blocking queue implementations in j.u.concurrent,
>> that probably have the same issue.
>>>
>>> We want Thread::stop to go away. We terminally deprecated and degraded
>> stop(Throwable) in Java 9 and finally removed the method in a later
>> release, the no-arg Thread::stop needs to go the same way. The first steps
>> for this are in the loom repo in the form of terminal deprecation, not
>> supported for virtual threads, and ThreadGroup::stop degraded to
>> unconditionally throw UOE. We've been hesitant to be move faster as there
>> may be usages in the wild where it is used instead of interrupt as a
>> cancellation mechanism.
>>>
>>> I should also say that debugger support (JDI/JDWP,JVMTI) has the
>> equivalent of stop(Throwable) for "managed" usages of async exceptions.
>> jshell uses a signal interrupt and JDI and maybe it's calling Thread.stop,
>> I need to check that as I can't otherwise explain why you see an issue with
>> ctrl-C in jshell.
>> Indeed, it is not always trivial changing from synchronized/wait to
>> Condition/await because of these subtle differences.
>>> -------------
>>>
>>> PR: https://git.openjdk.java.net/loom/pull/32
>>


More information about the loom-dev mailing list