RFR: avoid extra park of vthread when using fixed thread pool

Miao Zheng github.com+20216587+miao-zheng at openjdk.java.net
Thu Aug 26 07:28:10 UTC 2021


The test case of ParkWithFixedThreadPool.java create 300 virtual threads, each vthread(exclude latest vthread) park itself and unpark previous vthread. The expected result is any vthread can finish.

Running this test case in slowdebug and the test will random hang.

There are three vthreads which are vt-1, vt-2, vt-3;
(1) vt-1 take the ReentrantLock, and vt-2 try to unpark vt-1, and vt-2 fail to get ReentrantLock so it park itself( the call stack is shown below); 
(2)vt-3 unpark vt-2, and vt-2 try to get ReentrantLock again, but the ReentrantLock is still owned by vt-1, vt-2 park itself again;
(3)vt-1 release the ReentrantLock and unpark vt-2, vt-2 park itself at ParkWithFixedThreadPool.java:55, and it will never unpark.(because the unpark from vt-3 has consumed)

The reason is scheduler.execute() will try to alloc a Reentrant lock when using fix thread pool, the call stack is like:
    at java.lang.VirtualThread.tryPark(VirtualThread.java:472)
    at java.lang.VirtualThread.park(VirtualThread.java:424)
    at java.lang.System$2.parkVirtualThread(System.java:1279)
    at sun.misc.VirtualThreads.park(VirtualThreads.java:56)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:183)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)
    at java.util.concurrent.locks.ReentrantLock$NonfairSync.lock(ReentrantLock.java:209)
    at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)
    at java.util.concurrent.LinkedBlockingQueue.offer(LinkedBlockingQueue.java:418)
    at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1371)
    at java.lang.VirtualThread.unpark(VirtualThread.java:502)
    at java.lang.System$2.unparkVirtualThread(System.java:1287)
    at sun.misc.VirtualThreads.unpark(VirtualThreads.java:70)
    at ParkWithFixedThreadPool$1.run(ParkWithFixedThreadPool.java:51)


The solution is switch back to carrier thread before call scheduler.execute();

-------------

Commit messages:
 - avoid extra park of vthread when using fixed thread pool

Changes: https://git.openjdk.java.net/loom/pull/59/files
 Webrev: https://webrevs.openjdk.java.net/?repo=loom&pr=59&range=00
  Stats: 96 lines in 2 files changed: 95 ins; 0 del; 1 mod
  Patch: https://git.openjdk.java.net/loom/pull/59.diff
  Fetch: git fetch https://git.openjdk.java.net/loom pull/59/head:pull/59

PR: https://git.openjdk.java.net/loom/pull/59


More information about the loom-dev mailing list