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

Miao Zheng github.com+20216587+miao-zheng at openjdk.java.net
Mon Aug 30 12:32:42 UTC 2021


On Thu, 26 Aug 2021 07:21:16 GMT, Miao Zheng <github.com+20216587+miao-zheng at openjdk.org> wrote:

> 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();

This pull request has now been integrated.

Changeset: e0453677
Author:    miao zheng <emoryzheng at tencent.com>
Committer: Alan Bateman <alanb at openjdk.org>
URL:       https://git.openjdk.java.net/loom/commit/e0453677c9340e38a4a7fdc479c8068499fdce47
Stats:     84 lines in 2 files changed: 83 ins; 0 del; 1 mod

avoid extra park of vthread when using fixed thread pool

Reviewed-by: alanb

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

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


More information about the loom-dev mailing list