RFR: In rare cases, the unlock() on join() might fail, causing an IllegalMonitorStateException
Dr Heinz M. Kabutz
heinz at javaspecialists.eu
Thu Feb 25 14:32:38 UTC 2021
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