Fix ConcurrentBag yield spin loop with virtual threads#2399
Fix ConcurrentBag yield spin loop with virtual threads#2399TusharSariya wants to merge 1 commit into
Conversation
|
Thanks for putting this together. I ran this PR through the same small harness I used on #2398, comparing The good news: this does eliminate the virtual-thread Results from the 60s VT repro:
However, I also ran the upstream
So this branch fixes the VT yield symptom, but in this run it regressed the platform-thread I think the likely reason is that this changes the handoff behavior for all callers by replacing the existing spin/yield path with timed A narrower alternative is to keep the existing platform-thread behavior and only route virtual-thread callers to the existing |
Fixes #2398.
If a borrowing vt increments waiters but it is preempted before it can poll the handoff queue,
all requiter VTs can see there is a waiter and try to do an handoff, all the requiter VTs will hit
thread.yield(). This is a subtle scheduler race condition, it becomes visible with virtual threads
due to the number of threads that can be spawned.
Solution
Rather than a yield which keeps the thread runnable, use an interruptible park when doing an offer
to the handoff queue. This will park the requiter and allow any preempted borrowers to start polling
the handoff queue.
Tests:
I did not note any changes to performance or behaviour, tests are tricky and non deterministic.
Could not reproduce on JDK 25. Most likely cause is JDK-8319447, which integrated DelayScheduler
into ForkJoinPool and tightened virtual-thread timed-park entry. could not prove this.