From 9e963bcd279ba46a14f0e7fa13086dab51f007e5 Mon Sep 17 00:00:00 2001
From: Doug Lea
Date: Mon, 12 Jan 2026 12:17:35 -0500
Subject: [PATCH] Use explicit store fences or atomics
---
.../java/util/concurrent/ForkJoinPool.java | 35 +++++++++++--------
1 file changed, 20 insertions(+), 15 deletions(-)
diff --git a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
index adfc6d94d13..f12d05cac33 100644
--- a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
+++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
@@ -1255,11 +1255,11 @@ public class ForkJoinPool extends AbstractExecutorService
growAndPush(task, pool, unlock);
else {
top = s + 1;
- U.putReferenceVolatile(a, slotOffset(m & s), task);
+ U.getAndSetReference(a, slotOffset(m & s), task);
+ Object pred = U.getReferenceAcquire(a, slotOffset(m & (s - 1)));
if (unlock != 1) // release external lock
- U.putInt(this, PHASE, unlock);
- if (U.getReferenceAcquire(a, slotOffset(m & (s - 1))) == null &&
- pool != null)
+ phase = unlock;
+ if (pred == null && pool != null)
pool.signalWork(this, s); // may have appeared empty
}
}
@@ -1316,13 +1316,16 @@ public class ForkJoinPool extends AbstractExecutorService
if (a != null && s - b >= 0 && (cap = a.length) > 0) {
if (fifo == 0) {
if ((t = (ForkJoinTask>)U.getAndSetReference(
- a, slotOffset((cap - 1) & s), null)) != null)
+ a, slotOffset((cap - 1) & s), null)) != null) {
top = s;
+ U.storeFence();
+ }
} else {
do {
if ((t = (ForkJoinTask>)U.getAndSetReference(
a, slotOffset((cap - 1) & b), null)) != null) {
base = b + 1;
+ U.storeFence();
break;
}
if (b == s)
@@ -1339,10 +1342,7 @@ public class ForkJoinPool extends AbstractExecutorService
* Takes next task, if one exists, using configured mode.
*/
final ForkJoinTask> nextLocalTask() {
- U.loadFence(); // ensure ordering for external callers
- ForkJoinTask> t = nextLocalTask(config & FIFO);
- U.storeFence();
- return t;
+ return nextLocalTask(config & FIFO);
}
/**
@@ -1359,7 +1359,8 @@ public class ForkJoinPool extends AbstractExecutorService
(internal || (lock = tryLockPhase()) != 1)) {
if (top == p && U.compareAndSetReference(a, k, task, null)) {
taken = true;
- U.putIntOpaque(this, TOP, s);
+ top = s;
+ U.storeFence();
}
if (!internal)
phase = lock + NEXTIDLE;
@@ -1371,7 +1372,6 @@ public class ForkJoinPool extends AbstractExecutorService
* Returns next task, if one exists, in order specified by mode.
*/
final ForkJoinTask> peek() {
- U.loadFence(); // ensure ordering for external callers
ForkJoinTask>[] a = array;
int b = base, cfg = config, p = top, cap;
if (p != b && a != null && (cap = a.length) > 0) {
@@ -1392,7 +1392,6 @@ public class ForkJoinPool extends AbstractExecutorService
* Polls for a task. Used only by non-owners.
*/
final ForkJoinTask> poll() {
- U.loadFence(); // ensure ordering for external callers
for (int pb = -1, b; ; pb = b) { // track progress
ForkJoinTask> t; int cap, nb; long k; ForkJoinTask>[] a;
if ((a = array) == null || (cap = a.length) <= 0)
@@ -1410,7 +1409,8 @@ public class ForkJoinPool extends AbstractExecutorService
Thread.onSpinWait(); // stalled
}
else if (U.compareAndSetReference(a, k, t, null)) {
- U.putIntVolatile(this, BASE, nb);
+ base = nb;
+ U.storeFence();
return t;
}
}
@@ -1508,8 +1508,10 @@ public class ForkJoinPool extends AbstractExecutorService
break;
if (taken =
(top == p &&
- U.compareAndSetReference(a, k, t, null)))
- U.putIntOpaque(this, TOP, s);
+ U.compareAndSetReference(a, k, t, null))) {
+ top = s;
+ U.storeFence();
+ }
if (!internal)
phase = lock + NEXTIDLE;
if (!taken)
@@ -1547,6 +1549,7 @@ public class ForkJoinPool extends AbstractExecutorService
if (base == b && t != null &&
U.compareAndSetReference(a, k, t, null)) {
base = b + 1;
+ U.storeFence();
t.doExec();
}
}
@@ -2374,6 +2377,7 @@ public class ForkJoinPool extends AbstractExecutorService
if (U.compareAndSetReference(
a, k, t, null)) {
q.base = b + 1;
+ U.storeFence();
t.doExec();
locals = rescan = true;
break scan;
@@ -2799,6 +2803,7 @@ public class ForkJoinPool extends AbstractExecutorService
if (q.base == b && t != null &&
U.compareAndSetReference(a, k, t, null)) {
q.base = b + 1;
+ U.storeFence();
try {
t.cancel(false);
} catch (Throwable ignore) {