RFR: Update running count of ForkJoinPool when thread pinned [v2]

Alan Bateman alanb at openjdk.java.net
Tue Dec 21 10:28:31 UTC 2021


On Tue, 21 Dec 2021 01:38:12 GMT, Miao Zheng <duke at openjdk.java.net> wrote:

>> In the test case of this PR, when vt0 invoke System.out.println(), it will invoke managedBlock eventually, and create a new ForkJoinWorkerThread. The call stack is :
>> 
>> at java.base/java.util.concurrent.ForkJoinPool.tryCompensate(ForkJoinPool.java:1789)
>>         at java.base/java.util.concurrent.ForkJoinPool.compensatedBlock(ForkJoinPool.java:3448)
>>         at java.base/jdk.internal.misc.Blocker.managedBlock(Blocker.java:185)
>>         at java.base/java.io.FileOutputStream.write(FileOutputStream.java:365)
>>         at java.base/java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:126)
>>         at java.base/java.io.BufferedOutputStream.lockedFlush(BufferedOutputStream.java:251)
>>         at java.base/java.io.BufferedOutputStream.flush(BufferedOutputStream.java:239)
>>         at java.base/java.io.PrintStream.lockedWrite(PrintStream.java:655)
>>         at java.base/java.io.PrintStream.write(PrintStream.java:633)
>>         at java.base/sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:308)
>>         at java.base/sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:404)
>>         at java.base/sun.nio.cs.StreamEncoder.lockedFlushBuffer(StreamEncoder.java:126)
>>         at java.base/sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:113)
>>         at java.base/java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:176)
>>         at java.base/java.io.PrintStream.lockedWriteln(PrintStream.java:859)
>>         at java.base/java.io.PrintStream.writeln(PrintStream.java:836)
>>         at java.base/java.io.PrintStream.println(PrintStream.java:1178)
>>         at VTCompensate$1.run(VTCompensate.java:45)
>>         at java.base/java.lang.VirtualThread.run(VirtualThread.java:270)
>>         at java.base/java.lang.VirtualThread$VThreadContinuation.lambda$new$0(VirtualThread.java:155)
>>         at java.base/jdk.internal.vm.Continuation.enter0(Continuation.java:377)
>>         at java.base/jdk.internal.vm.Continuation.enter(Continuation.java:370)
>> 
>> 
>> After create a new ForkJoinWorkerThread, we have two ForkJoinWorkerThread(use -Djdk.defaultScheduler.parallelism=1 for initialization), and vt1 pinned a ForkJoinWorkerThread.
>> 
>> When main thread unlock Reentrantlock, vt0 will re-submit to ForkJoinPool and we have an extra working thread to run vt0. 
>> 
>> But we find the extra compensate working thread not work, it is parked. The call stack is :
>> 
>> "ForkJoinPool-1-worker-2" #18 [31814] daemon prio=5 os_prio=0 cpu=0.42ms elapsed=119.94s tid=0x00007f8cf8005050 nid=31814 waiting on condition  [0x00007f8d4012c000]
>>    java.lang.Thread.State: WAITING (parking)
>>         at jdk.internal.misc.Unsafe.park(java.base at 19-internal/Native Method)
>>         at java.util.concurrent.locks.LockSupport.park(java.base at 19-internal/LockSupport.java:371)
>>         at java.util.concurrent.ForkJoinPool.awaitWork(java.base at 19-internal/ForkJoinPool.java:1706)
>>         at java.util.concurrent.ForkJoinPool.runWorker(java.base at 19-internal/ForkJoinPool.java:1603)
>>         at java.util.concurrent.ForkJoinWorkerThread.run(java.base at 19-internal/ForkJoinWorkerThread.java:165)
>> 
>> 
>> The problem is when re-submit vt-0 to ForkJoinPool, it will call signalWork() of ForkJoinPool and signalWork() do nothing because current c > 0L and the judgement of c < 0L will jump over the loop(c < 0L means RC < parallelism, in our test case, parallelism is 1 and current running count is 1)
>> 
>> Actually, current running count should be 0 now because pinned thread can not running other task, so we think should update running count of ForkJoinPool before and after pin.
>
> Miao Zheng has refreshed the contents of this pull request, and previous commits have been removed. The incremental views will show differences compared to the previous content of the PR. The pull request contains one new commit since the last revision:
> 
>   Update running count of ForkJoinPool when thread pinned

I don't think we should do this, at least not as proposed. We either consistently compensate or not compensate, it's just too unpredictable to try to make use of idle workers when parallelism has not been increased.  In PR 80, Ron argued that pinning should not compensate so we either have to re-visit that issue or do nothing. 

I also have a concern with the APIs exposed because (a) the FJP API doesn't expose anything about release counts, and (b) the Thread object for carrier threads is not exposed.

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

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


More information about the loom-dev mailing list