From d3bf00f4cf91c09f863d5690fec40ccfbe5e92cd Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Mon, 26 May 2025 08:11:13 -0400 Subject: [PATCH 01/12] Reduce branchiness of Exchanger --- .../java/util/concurrent/Exchanger.java | 84 ++++++++----------- 1 file changed, 37 insertions(+), 47 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/Exchanger.java b/src/java.base/share/classes/java/util/concurrent/Exchanger.java index 75de69b3e5283..e41f8c051a853 100644 --- a/src/java.base/share/classes/java/util/concurrent/Exchanger.java +++ b/src/java.base/share/classes/java/util/concurrent/Exchanger.java @@ -276,10 +276,10 @@ static final class Node { int index; // Arena index Object item; // This thread's current item volatile Object match; // Item provided by releasing thread - volatile Thread parked; // Set to this thread when parked, else null + final Thread thread; Node() { index = -1; // initialize on first use - seed = Thread.currentThread().threadId(); + seed = (thread = Thread.currentThread()).threadId(); } } @@ -329,10 +329,10 @@ private final V xchg(V x, long deadline) Participant ps = participant; Object item = (x == null) ? ps : x; // translate nulls Node p = ps.get(); + p.item = item; int i = p.index; // if < 0, move int misses = 0; // ++ on collide, -- on spinout - Object offered = null; // for cleanup - Object v = null; + Object v; // the match outer: for (;;) { int b, m; Slot s; Node q; if ((m = (b = bound) & MMASK) == 0) // volatile read @@ -344,11 +344,10 @@ private final V xchg(V x, long deadline) } else if ((q = s.entry) != null) { // try release if (ENTRY.compareAndSet(s, q, null)) { - Thread w; v = q.item; q.match = item; - if (i == 0 && (w = q.parked) != null) - LockSupport.unpark(w); + if (i == 0) + LockSupport.unpark(q.thread); break; } else { // collision @@ -366,47 +365,39 @@ else if ((nb = (b + 1) & MMASK) < alen) { } } } - else { // try offer - if (offered == null) - offered = p.item = item; - if (ENTRY.compareAndSet(s, null, p)) { - boolean tryCancel; // true if interrupted - Thread t = Thread.currentThread(); - if (!(tryCancel = t.isInterrupted()) && ncpu > 1 && - (i != 0 || // check for busy VTs - (!ForkJoinWorkerThread.hasKnownQueuedWork()))) { - for (int j = SPINS; j > 0; --j) { - if ((v = p.match) != null) { - MATCH.set(p, null); - break outer; // spin wait - } - Thread.onSpinWait(); + else if (ENTRY.compareAndSet(s, null, p)) { // try offer + boolean tryCancel = false; + for (long ns = 1L;;) { + if (p.match == null && !tryCancel) { + if ((deadline != 0L && + (ns = deadline - System.nanoTime()) <= 0L) || + Thread.currentThread().isInterrupted()) + tryCancel = true; // cancel unless match + else if (ncpu > 1 && + (i != 0 || // check for busy VTs + (!ForkJoinWorkerThread.hasKnownQueuedWork()))) { + for (int j = SPINS; p.match == null && j > 0; --j) + Thread.onSpinWait(); } } - for (long ns = 1L;;) { // block or cancel offer - if ((v = p.match) != null) { - MATCH.set(p, null); - break outer; - } - if (i == 0 && !tryCancel && - (deadline == 0L || - ((ns = deadline - System.nanoTime()) > 0L))) { - p.parked = t; // emable unpark and recheck - if (p.match == null) { - if (deadline == 0L) - LockSupport.park(this); - else - LockSupport.parkNanos(this, ns); - tryCancel = t.isInterrupted(); - } - p.parked = null; - } - else if (ENTRY.compareAndSet(s, p, null)) { // cancel - offered = p.item = null; - if (Thread.interrupted()) + if ((v = MATCH.getAndSet(p, null)) != null) + break outer; + else if (!tryCancel && i == 0) { + if (deadline == 0L) + LockSupport.park(this); + else + LockSupport.parkNanos(this, ns); + } + else if (ENTRY.compareAndSet(s, p, null)) { // cancel + boolean interrupted = Thread.interrupted(); + if (interrupted || ns <= 0L) { + p.item = null; + if (interrupted) throw new InterruptedException(); - if (deadline != 0L && ns <= 0L) + else throw new TimeoutException(); + } + else { i = -1; // move and restart if (bound != b) misses = 0; // stale @@ -416,14 +407,13 @@ else if ((b & MMASK) != 0) { misses = 0; // try to shrink BOUND.compareAndSet(this, b, b - 1 + SEQ); } - continue outer; + break; } } } } } - if (offered != null) // cleanup - p.item = null; + p.item = null; // cleanup @SuppressWarnings("unchecked") V ret = (v == participant) ? null : (V)v; return ret; } From 954c5a1817ca537d0fe2401ea053631b21adf60c Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Wed, 18 Jun 2025 12:45:04 -0400 Subject: [PATCH 02/12] Initial set of doc updates --- .../java/util/concurrent/CompletionStage.java | 263 +++++++++--------- .../classes/java/util/concurrent/Flow.java | 3 +- .../java/util/concurrent/ForkJoinPool.java | 12 +- .../concurrent/ScheduledExecutorService.java | 16 +- .../ScheduledThreadPoolExecutor.java | 6 +- .../util/concurrent/SubmissionPublisher.java | 10 +- .../atomic/AtomicReferenceFieldUpdater.java | 2 +- 7 files changed, 163 insertions(+), 149 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/CompletionStage.java b/src/java.base/share/classes/java/util/concurrent/CompletionStage.java index 6ff31c61049cf..0dc320aeee08a 100644 --- a/src/java.base/share/classes/java/util/concurrent/CompletionStage.java +++ b/src/java.base/share/classes/java/util/concurrent/CompletionStage.java @@ -43,7 +43,7 @@ /** * A stage of a possibly asynchronous computation, that performs an * action or computes a value when another CompletionStage completes. - * A stage completes upon termination of its computation, but this may + * A stage completes upon termination of its computation, which may * in turn trigger other dependent stages. The functionality defined * in this interface takes only a few basic forms, which expand out to * a larger set of methods to capture a range of usage styles: @@ -97,18 +97,21 @@ * In all other cases, if a stage's computation terminates abruptly * with an (unchecked) exception or error, then all dependent stages * requiring its completion complete exceptionally as well, with a - * {@link CompletionException} holding the exception as its cause. If - * a stage is dependent on both of two stages, and both - * complete exceptionally, then the CompletionException may correspond - * to either one of these exceptions. If a stage is dependent on - * either of two others, and only one of them completes - * exceptionally, no guarantees are made about whether the dependent - * stage completes normally or exceptionally. In the case of method - * {@code whenComplete}, when the supplied action itself encounters an - * exception, then the stage completes exceptionally with this - * exception unless the source stage also completed exceptionally, in - * which case the exceptional completion from the source stage is - * given preference and propagated to the dependent stage. + * {@link CompletionException} holding the exception as its + * cause. This distinguishes exceptions in an action itself from those + * it depends on. If you want them handled in the same way, you might + * choose to catch {@link RuntimeException}. If a stage is dependent + * on both of two stages, and both complete exceptionally, + * then the CompletionException may correspond to either one of these + * exceptions. If a stage is dependent on either of two + * others, and only one of them completes exceptionally, no guarantees + * are made about whether the dependent stage completes normally or + * exceptionally. In the case of method {@code whenComplete}, when the + * supplied action itself encounters an exception, then the stage + * completes exceptionally with that exception unless the source stage + * also completed exceptionally, in which case the exceptional + * completion from the source stage is given preference and propagated + * to the dependent stage. * * * @@ -137,7 +140,7 @@ * } * }} * - *

This interface does not define methods for initially creating, + *

The {@code CompletionStage} interface does not define methods for initially creating, * forcibly completing normally or exceptionally, probing completion * status or results, or awaiting completion of a stage. * Implementations of CompletionStage may provide means of achieving @@ -145,6 +148,12 @@ * enables interoperability among different implementations of this * interface by providing a common conversion type. * + *

Memory consistency effects: Actions in a thread prior to the + * submission of a computation producing a {@code CompletionStage} + * happen-before that computation begins. And actions taken by + * a {@code CompletionStage} happen-before actions of any + * dependent stage subsequent to its completion. + * * @param the type of values the stage produces or consumes * * @author Doug Lea @@ -153,8 +162,8 @@ public interface CompletionStage { /** - * Returns a new CompletionStage that, when this stage completes - * normally, is executed with this stage's result as the argument + * Returns a new CompletionStage that, when {@code this} stage completes + * normally, is executed with {@code this} stage's result as the argument * to the supplied function. * *

This method is analogous to @@ -172,9 +181,9 @@ public interface CompletionStage { public CompletionStage thenApply(Function fn); /** - * Returns a new CompletionStage that, when this stage completes - * normally, is executed using this stage's default asynchronous - * execution facility, with this stage's result as the argument to + * Returns a new CompletionStage that, when {@code this} stage completes + * normally, is executed using {@code this} stage's default asynchronous + * execution facility, with {@code this} stage's result as the argument to * the supplied function. * * See the {@link CompletionStage} documentation for rules @@ -189,8 +198,8 @@ public interface CompletionStage { (Function fn); /** - * Returns a new CompletionStage that, when this stage completes - * normally, is executed using the supplied Executor, with this + * Returns a new CompletionStage that, when {@code this} stage completes + * normally, is executed using the supplied Executor, with {@code this} * stage's result as the argument to the supplied function. * * See the {@link CompletionStage} documentation for rules @@ -207,8 +216,8 @@ public interface CompletionStage { Executor executor); /** - * Returns a new CompletionStage that, when this stage completes - * normally, is executed with this stage's result as the argument + * Returns a new CompletionStage that, when {@code this} stage completes + * normally, is executed with {@code this} stage's result as the argument * to the supplied action. * * See the {@link CompletionStage} documentation for rules @@ -221,9 +230,9 @@ public interface CompletionStage { public CompletionStage thenAccept(Consumer action); /** - * Returns a new CompletionStage that, when this stage completes - * normally, is executed using this stage's default asynchronous - * execution facility, with this stage's result as the argument to + * Returns a new CompletionStage that, when {@code this} stage completes + * normally, is executed using {@code this} stage's default asynchronous + * execution facility, with {@code this} stage's result as the argument to * the supplied action. * * See the {@link CompletionStage} documentation for rules @@ -236,8 +245,8 @@ public interface CompletionStage { public CompletionStage thenAcceptAsync(Consumer action); /** - * Returns a new CompletionStage that, when this stage completes - * normally, is executed using the supplied Executor, with this + * Returns a new CompletionStage that, when {@code this} stage completes + * normally, is executed using the supplied Executor, with {@code this} * stage's result as the argument to the supplied action. * * See the {@link CompletionStage} documentation for rules @@ -251,7 +260,7 @@ public interface CompletionStage { public CompletionStage thenAcceptAsync(Consumer action, Executor executor); /** - * Returns a new CompletionStage that, when this stage completes + * Returns a new CompletionStage that, when {@code this} stage completes * normally, executes the given action. * * See the {@link CompletionStage} documentation for rules @@ -264,8 +273,8 @@ public CompletionStage thenAcceptAsync(Consumer action, public CompletionStage thenRun(Runnable action); /** - * Returns a new CompletionStage that, when this stage completes - * normally, executes the given action using this stage's default + * Returns a new CompletionStage that, when {@code this} stage completes + * normally, executes the given action using {@code this} stage's default * asynchronous execution facility. * * See the {@link CompletionStage} documentation for rules @@ -278,7 +287,7 @@ public CompletionStage thenAcceptAsync(Consumer action, public CompletionStage thenRunAsync(Runnable action); /** - * Returns a new CompletionStage that, when this stage completes + * Returns a new CompletionStage that, when {@code this} stage completes * normally, executes the given action using the supplied Executor. * * See the {@link CompletionStage} documentation for rules @@ -293,7 +302,7 @@ public CompletionStage thenRunAsync(Runnable action, Executor executor); /** - * Returns a new CompletionStage that, when this and the other + * Returns a new CompletionStage that, when {@code this} and the other * given stage both complete normally, is executed with the two * results as arguments to the supplied function. * @@ -312,8 +321,8 @@ public CompletionStage thenRunAsync(Runnable action, BiFunction fn); /** - * Returns a new CompletionStage that, when this and the other - * given stage both complete normally, is executed using this + * Returns a new CompletionStage that, when {@code this} and the other + * given stage both complete normally, is executed using {@code this} * stage's default asynchronous execution facility, with the two * results as arguments to the supplied function. * @@ -332,7 +341,7 @@ public CompletionStage thenRunAsync(Runnable action, BiFunction fn); /** - * Returns a new CompletionStage that, when this and the other + * Returns a new CompletionStage that, when {@code this} and the other * given stage both complete normally, is executed using the * supplied executor, with the two results as arguments to the * supplied function. @@ -354,7 +363,7 @@ public CompletionStage thenRunAsync(Runnable action, Executor executor); /** - * Returns a new CompletionStage that, when this and the other + * Returns a new CompletionStage that, when {@code this} and the other * given stage both complete normally, is executed with the two * results as arguments to the supplied action. * @@ -372,8 +381,8 @@ public CompletionStage thenRunAsync(Runnable action, BiConsumer action); /** - * Returns a new CompletionStage that, when this and the other - * given stage both complete normally, is executed using this + * Returns a new CompletionStage that, when {@code this} and the other + * given stage both complete normally, is executed using {@code this} * stage's default asynchronous execution facility, with the two * results as arguments to the supplied action. * @@ -391,7 +400,7 @@ public CompletionStage thenRunAsync(Runnable action, BiConsumer action); /** - * Returns a new CompletionStage that, when this and the other + * Returns a new CompletionStage that, when {@code this} and the other * given stage both complete normally, is executed using the * supplied executor, with the two results as arguments to the * supplied action. @@ -412,7 +421,7 @@ public CompletionStage thenRunAsync(Runnable action, Executor executor); /** - * Returns a new CompletionStage that, when this and the other + * Returns a new CompletionStage that, when {@code this} and the other * given stage both complete normally, executes the given action. * * See the {@link CompletionStage} documentation for rules @@ -426,9 +435,9 @@ public CompletionStage thenRunAsync(Runnable action, public CompletionStage runAfterBoth(CompletionStage other, Runnable action); /** - * Returns a new CompletionStage that, when this and the other + * Returns a new CompletionStage that, when {@code this} and the other * given stage both complete normally, executes the given action - * using this stage's default asynchronous execution facility. + * using {@code this} stage's default asynchronous execution facility. * * See the {@link CompletionStage} documentation for rules * covering exceptional completion. @@ -442,7 +451,7 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Runnable action); /** - * Returns a new CompletionStage that, when this and the other + * Returns a new CompletionStage that, when {@code this} and the other * given stage both complete normally, executes the given action * using the supplied executor. * @@ -459,7 +468,7 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Runnable action, Executor executor); /** - * Returns a new CompletionStage that, when either this or the + * Returns a new CompletionStage that, when either {@code this} or the * other given stage complete normally, is executed with the * corresponding result as argument to the supplied function. * @@ -477,8 +486,8 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Function fn); /** - * Returns a new CompletionStage that, when either this or the - * other given stage complete normally, is executed using this + * Returns a new CompletionStage that, when either {@code this} or the + * other given stage complete normally, is executed using {@code this} * stage's default asynchronous execution facility, with the * corresponding result as argument to the supplied function. * @@ -496,7 +505,7 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Function fn); /** - * Returns a new CompletionStage that, when either this or the + * Returns a new CompletionStage that, when either {@code this} or the * other given stage complete normally, is executed using the * supplied executor, with the corresponding result as argument to * the supplied function. @@ -517,7 +526,7 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Executor executor); /** - * Returns a new CompletionStage that, when either this or the + * Returns a new CompletionStage that, when either {@code this} or the * other given stage complete normally, is executed with the * corresponding result as argument to the supplied action. * @@ -534,8 +543,8 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Consumer action); /** - * Returns a new CompletionStage that, when either this or the - * other given stage complete normally, is executed using this + * Returns a new CompletionStage that, when either {@code this} or the + * other given stage complete normally, is executed using {@code this} * stage's default asynchronous execution facility, with the * corresponding result as argument to the supplied action. * @@ -552,7 +561,7 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Consumer action); /** - * Returns a new CompletionStage that, when either this or the + * Returns a new CompletionStage that, when either {@code this} or the * other given stage complete normally, is executed using the * supplied executor, with the corresponding result as argument to * the supplied action. @@ -572,7 +581,7 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Executor executor); /** - * Returns a new CompletionStage that, when either this or the + * Returns a new CompletionStage that, when either {@code this} or the * other given stage complete normally, executes the given action. * * See the {@link CompletionStage} documentation for rules @@ -587,9 +596,9 @@ public CompletionStage runAfterEither(CompletionStage other, Runnable action); /** - * Returns a new CompletionStage that, when either this or the + * Returns a new CompletionStage that, when either {@code this} or the * other given stage complete normally, executes the given action - * using this stage's default asynchronous execution facility. + * using {@code this} stage's default asynchronous execution facility. * * See the {@link CompletionStage} documentation for rules * covering exceptional completion. @@ -604,7 +613,7 @@ public CompletionStage runAfterEither(CompletionStage other, Runnable action); /** - * Returns a new CompletionStage that, when either this or the + * Returns a new CompletionStage that, when either {@code this} or the * other given stage complete normally, executes the given action * using the supplied executor. * @@ -626,10 +635,10 @@ public CompletionStage runAfterEither(CompletionStage other, * Returns a new CompletionStage that is completed with the same * value as the CompletionStage returned by the given function. * - *

When this stage completes normally, the given function is - * invoked with this stage's result as the argument, returning + *

When {@code this} stage completes normally, the given function is + * invoked with {@code this} stage's result as the argument, returning * another CompletionStage. When that stage completes normally, - * the CompletionStage returned by this method is completed with + * the CompletionStage returned is completed with * the same value. * *

To ensure progress, the supplied function must arrange @@ -652,13 +661,13 @@ public CompletionStage runAfterEither(CompletionStage other, /** * Returns a new CompletionStage that is completed with the same * value as the CompletionStage returned by the given function, - * executed using this stage's default asynchronous execution + * executed using {@code this} stage's default asynchronous execution * facility. * - *

When this stage completes normally, the given function is - * invoked with this stage's result as the argument, returning + *

When {@code this} stage completes normally, the given function is + * invoked with {@code this} stage's result as the argument, returning * another CompletionStage. When that stage completes normally, - * the CompletionStage returned by this method is completed with + * the CompletionStage returned is completed with * the same value. * *

To ensure progress, the supplied function must arrange @@ -679,10 +688,10 @@ public CompletionStage runAfterEither(CompletionStage other, * value as the CompletionStage returned by the given function, * executed using the supplied Executor. * - *

When this stage completes normally, the given function is - * invoked with this stage's result as the argument, returning + *

When {@code this} stage completes normally, the given function is + * invoked with {@code this} stage's result as the argument, returning * another CompletionStage. When that stage completes normally, - * the CompletionStage returned by this method is completed with + * the CompletionStage returned by {@code this} method is completed with * the same value. * *

To ensure progress, the supplied function must arrange @@ -701,13 +710,13 @@ public CompletionStage runAfterEither(CompletionStage other, Executor executor); /** - * Returns a new CompletionStage that, when this stage completes - * either normally or exceptionally, is executed with this stage's + * Returns a new CompletionStage that, when {@code this} stage completes + * either normally or exceptionally, is executed with {@code this} stage's * result and exception as arguments to the supplied function. * - *

When this stage is complete, the given function is invoked + *

When {@code this} stage is complete, the given function is invoked * with the result (or {@code null} if none) and the exception (or - * {@code null} if none) of this stage as arguments, and the + * {@code null} if none) of {@code this} stage as arguments, and the * function's result is used to complete the returned stage. * * @param fn the function to use to compute the value of the @@ -719,14 +728,14 @@ public CompletionStage runAfterEither(CompletionStage other, (BiFunction fn); /** - * Returns a new CompletionStage that, when this stage completes - * either normally or exceptionally, is executed using this stage's - * default asynchronous execution facility, with this stage's + * Returns a new CompletionStage that, when {@code this} stage completes + * either normally or exceptionally, is executed using {@code this} stage's + * default asynchronous execution facility, with {@code this} stage's * result and exception as arguments to the supplied function. * - *

When this stage is complete, the given function is invoked + *

When {@code this} stage is complete, the given function is invoked * with the result (or {@code null} if none) and the exception (or - * {@code null} if none) of this stage as arguments, and the + * {@code null} if none) of {@code this} stage as arguments, and the * function's result is used to complete the returned stage. * * @param fn the function to use to compute the value of the @@ -738,14 +747,14 @@ public CompletionStage runAfterEither(CompletionStage other, (BiFunction fn); /** - * Returns a new CompletionStage that, when this stage completes + * Returns a new CompletionStage that, when {@code this} stage completes * either normally or exceptionally, is executed using the - * supplied executor, with this stage's result and exception as + * supplied executor, with {@code this} stage's result and exception as * arguments to the supplied function. * - *

When this stage is complete, the given function is invoked + *

When {@code this} stage is complete, the given function is invoked * with the result (or {@code null} if none) and the exception (or - * {@code null} if none) of this stage as arguments, and the + * {@code null} if none) of {@code this} stage as arguments, and the * function's result is used to complete the returned stage. * * @param fn the function to use to compute the value of the @@ -760,22 +769,22 @@ public CompletionStage runAfterEither(CompletionStage other, /** * Returns a new CompletionStage with the same result or exception as - * this stage, that executes the given action when this stage completes. + * {@code this} stage, that executes the given action when {@code this} stage completes. * - *

When this stage is complete, the given action is invoked + *

When {@code this} stage is complete, the given action is invoked * with the result (or {@code null} if none) and the exception (or - * {@code null} if none) of this stage as arguments. The returned + * {@code null} if none) of {@code this} stage as arguments. The returned * stage is completed when the action returns. * *

Unlike method {@link #handle handle}, - * this method is not designed to translate completion outcomes, + * method {@code whenComplete} is not designed to translate completion outcomes, * so the supplied action should not throw an exception. However, - * if it does, the following rules apply: if this stage completed + * if it does, the following rules apply: if {@code this} stage completed * normally but the supplied action throws an exception, then the * returned stage completes exceptionally with the supplied - * action's exception. Or, if this stage completed exceptionally + * action's exception. Or, if {@code this} stage completed exceptionally * and the supplied action throws an exception, then the returned - * stage completes exceptionally with this stage's exception. + * stage completes exceptionally with {@code this} stage's exception. * * @param action the action to perform * @return the new CompletionStage @@ -785,23 +794,23 @@ public CompletionStage runAfterEither(CompletionStage other, /** * Returns a new CompletionStage with the same result or exception as - * this stage, that executes the given action using this stage's - * default asynchronous execution facility when this stage completes. + * {@code this} stage, that executes the given action using {@code this} stage's + * default asynchronous execution facility when {@code this} stage completes. * - *

When this stage is complete, the given action is invoked with the + *

When {@code this} stage is complete, the given action is invoked with the * result (or {@code null} if none) and the exception (or {@code null} - * if none) of this stage as arguments. The returned stage is completed + * if none) of {@code this} stage as arguments. The returned stage is completed * when the action returns. * *

Unlike method {@link #handleAsync(BiFunction) handleAsync}, - * this method is not designed to translate completion outcomes, + * method {@code whenCompleteAsync} is not designed to translate completion outcomes, * so the supplied action should not throw an exception. However, - * if it does, the following rules apply: If this stage completed + * if it does, the following rules apply: If {@code this} stage completed * normally but the supplied action throws an exception, then the * returned stage completes exceptionally with the supplied - * action's exception. Or, if this stage completed exceptionally + * action's exception. Or, if {@code this} stage completed exceptionally * and the supplied action throws an exception, then the returned - * stage completes exceptionally with this stage's exception. + * stage completes exceptionally with {@code this} stage's exception. * * @param action the action to perform * @return the new CompletionStage @@ -811,23 +820,23 @@ public CompletionStage runAfterEither(CompletionStage other, /** * Returns a new CompletionStage with the same result or exception as - * this stage, that executes the given action using the supplied - * Executor when this stage completes. + * {@code this} stage, that executes the given action using the supplied + * Executor when {@code this} stage completes. * - *

When this stage is complete, the given action is invoked with the + *

When {@code this} stage is complete, the given action is invoked with the * result (or {@code null} if none) and the exception (or {@code null} - * if none) of this stage as arguments. The returned stage is completed + * if none) of {@code this} stage as arguments. The returned stage is completed * when the action returns. * *

Unlike method {@link #handleAsync(BiFunction,Executor) handleAsync}, - * this method is not designed to translate completion outcomes, + * method {@code whenCompleteAsync} is not designed to translate completion outcomes, * so the supplied action should not throw an exception. However, - * if it does, the following rules apply: If this stage completed + * if it does, the following rules apply: If {@code this} stage completed * normally but the supplied action throws an exception, then the * returned stage completes exceptionally with the supplied - * action's exception. Or, if this stage completed exceptionally + * action's exception. Or, if {@code this} stage completed exceptionally * and the supplied action throws an exception, then the returned - * stage completes exceptionally with this stage's exception. + * stage completes exceptionally with {@code this} stage's exception. * * @param action the action to perform * @param executor the executor to use for asynchronous execution @@ -838,14 +847,14 @@ public CompletionStage runAfterEither(CompletionStage other, Executor executor); /** - * Returns a new CompletionStage that, when this stage completes - * exceptionally, is executed with this stage's exception as the - * argument to the supplied function. Otherwise, if this stage + * Returns a new CompletionStage that, when {@code this} stage completes + * exceptionally, is executed with {@code this} stage's exception as the + * argument to the supplied function. Otherwise, if {@code this} stage * completes normally, then the returned stage also completes * normally with the same value. * * @param fn the function to use to compute the value of the - * returned CompletionStage if this CompletionStage completed + * returned CompletionStage if {@code this} CompletionStage completed * exceptionally * @return the new CompletionStage */ @@ -853,10 +862,10 @@ public CompletionStage runAfterEither(CompletionStage other, (Function fn); /** - * Returns a new CompletionStage that, when this stage completes - * exceptionally, is executed with this stage's exception as the - * argument to the supplied function, using this stage's default - * asynchronous execution facility. Otherwise, if this stage + * Returns a new CompletionStage that, when {@code this} stage completes + * exceptionally, is executed with {@code this} stage's exception as the + * argument to the supplied function, using {@code this} stage's default + * asynchronous execution facility. Otherwise, if {@code this} stage * completes normally, then the returned stage also completes * normally with the same value. * @@ -865,7 +874,7 @@ public CompletionStage runAfterEither(CompletionStage other, * #thenCompose} for result. * * @param fn the function to use to compute the value of the - * returned CompletionStage if this CompletionStage completed + * returned CompletionStage if {@code this} CompletionStage completed * exceptionally * @return the new CompletionStage * @since 12 @@ -879,10 +888,10 @@ public CompletionStage runAfterEither(CompletionStage other, } /** - * Returns a new CompletionStage that, when this stage completes - * exceptionally, is executed with this stage's exception as the + * Returns a new CompletionStage that, when {@code this} stage completes + * exceptionally, is executed with {@code this} stage's exception as the * argument to the supplied function, using the supplied Executor. - * Otherwise, if this stage completes normally, then the returned + * Otherwise, if {@code this} stage completes normally, then the returned * stage also completes normally with the same value. * * @implSpec The default implementation invokes {@link #handle}, @@ -890,7 +899,7 @@ public CompletionStage runAfterEither(CompletionStage other, * #thenCompose} for result. * * @param fn the function to use to compute the value of the - * returned CompletionStage if this CompletionStage completed + * returned CompletionStage if {@code this} CompletionStage completed * exceptionally * @param executor the executor to use for asynchronous execution * @return the new CompletionStage @@ -905,16 +914,16 @@ public CompletionStage runAfterEither(CompletionStage other, } /** - * Returns a new CompletionStage that, when this stage completes + * Returns a new CompletionStage that, when {@code this} stage completes * exceptionally, is composed using the results of the supplied - * function applied to this stage's exception. + * function applied to {@code this} stage's exception. * * @implSpec The default implementation invokes {@link #handle}, * invoking the given function on exception, then {@link * #thenCompose} for result. * * @param fn the function to use to compute the returned - * CompletionStage if this CompletionStage completed exceptionally + * CompletionStage if {@code this} CompletionStage completed exceptionally * @return the new CompletionStage * @since 12 */ @@ -927,9 +936,9 @@ public CompletionStage runAfterEither(CompletionStage other, } /** - * Returns a new CompletionStage that, when this stage completes + * Returns a new CompletionStage that, when {@code this} stage completes * exceptionally, is composed using the results of the supplied - * function applied to this stage's exception, using this stage's + * function applied to {@code this} stage's exception, using {@code this} stage's * default asynchronous execution facility. * * @implSpec The default implementation invokes {@link #handle}, @@ -937,7 +946,7 @@ public CompletionStage runAfterEither(CompletionStage other, * #thenCompose} for result. * * @param fn the function to use to compute the returned - * CompletionStage if this CompletionStage completed exceptionally + * CompletionStage if {@code this} CompletionStage completed exceptionally * @return the new CompletionStage * @since 12 */ @@ -951,9 +960,9 @@ public CompletionStage runAfterEither(CompletionStage other, } /** - * Returns a new CompletionStage that, when this stage completes + * Returns a new CompletionStage that, when {@code this} stage completes * exceptionally, is composed using the results of the supplied - * function applied to this stage's exception, using the + * function applied to {@code this} stage's exception, using the * supplied Executor. * * @implSpec The default implementation invokes {@link #handle}, @@ -961,7 +970,7 @@ public CompletionStage runAfterEither(CompletionStage other, * #thenCompose} for result. * * @param fn the function to use to compute the returned - * CompletionStage if this CompletionStage completed exceptionally + * CompletionStage if {@code this} CompletionStage completed exceptionally * @param executor the executor to use for asynchronous execution * @return the new CompletionStage * @since 12 @@ -978,9 +987,9 @@ public CompletionStage runAfterEither(CompletionStage other, /** * Returns a {@link CompletableFuture} maintaining the same - * completion properties as this stage. If this stage is already a - * CompletableFuture, this method may return this stage itself. - * Otherwise, invocation of this method may be equivalent in + * completion properties as {@code this} stage. If {@code this} stage is already a + * CompletableFuture, method {@code toCompletableFuture} may return {@code this} stage itself. + * Otherwise, invocation may be equivalent in * effect to {@code thenApply(x -> x)}, but returning an instance * of type {@code CompletableFuture}. * diff --git a/src/java.base/share/classes/java/util/concurrent/Flow.java b/src/java.base/share/classes/java/util/concurrent/Flow.java index 1aefaea43b0e3..d0590d08fbd48 100644 --- a/src/java.base/share/classes/java/util/concurrent/Flow.java +++ b/src/java.base/share/classes/java/util/concurrent/Flow.java @@ -60,7 +60,8 @@ * TRUE} item to a single subscriber. Because the subscriber receives * only a single item, this class does not use buffering and ordering * control required in most implementations (for example {@link - * SubmissionPublisher}). + * SubmissionPublisher}), and omits some error processing needed to + * fully conform to ReactiveStream rules. * *

 {@code
  * class OneShotPublisher implements Publisher {
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 a7821921bc911..9262003a92deb 100644
--- a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
+++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
@@ -140,7 +140,7 @@
  * tasks, as well as method {@link #submitWithTimeout} to cancel tasks
  * that take too long. The scheduled functions or actions may create
  * and invoke other {@linkplain ForkJoinTask ForkJoinTasks}. Delayed
- * actions become enabled and behave as ordinary submitted
+ * actions become enabled for execution and behave as ordinary submitted
  * tasks when their delays elapse.  Scheduling methods return
  * {@linkplain ForkJoinTask ForkJoinTasks} that implement the {@link
  * ScheduledFuture} interface. Resource exhaustion encountered after
@@ -153,7 +153,7 @@
  * to disable all delayed tasks upon shutdown, and method {@link
  * #shutdownNow} may be used to instead unconditionally initiate pool
  * termination. Monitoring methods such as {@link #getQueuedTaskCount}
- * do not include scheduled tasks that are not yet enabled to execute,
+ * do not include scheduled tasks that are not yet enabled for execution,
  * which are reported separately by method {@link
  * #getDelayedTaskCount}.
  *
@@ -3505,7 +3505,7 @@ final  ScheduledForkJoinTask scheduleDelayedTask(ScheduledForkJoinTask
     }
 
     /**
-     * Submits a one-shot task that becomes enabled after the given
+     * Submits a one-shot task that becomes enabled for execution after the given
      * delay.  At that point it will execute unless explicitly
      * cancelled, or fail to execute (eventually reporting
      * cancellation) when encountering resource exhaustion, or the
@@ -3533,7 +3533,7 @@ public ScheduledFuture schedule(Runnable command,
     }
 
     /**
-     * Submits a value-returning one-shot task that becomes enabled
+     * Submits a value-returning one-shot task that becomes enabled for execution
      * after the given delay. At that point it will execute unless
      * explicitly cancelled, or fail to execute (eventually reporting
      * cancellation) when encountering resource exhaustion, or the
@@ -3562,7 +3562,7 @@ public  ScheduledFuture schedule(Callable callable,
     }
 
     /**
-     * Submits a periodic action that becomes enabled first after the
+     * Submits a periodic action that becomes enabled for execution first after the
      * given initial delay, and subsequently with the given period;
      * that is, executions will commence after
      * {@code initialDelay}, then {@code initialDelay + period}, then
@@ -3616,7 +3616,7 @@ public ScheduledFuture scheduleAtFixedRate(Runnable command,
     }
 
     /**
-     * Submits a periodic action that becomes enabled first after the
+     * Submits a periodic action that becomes enabled for execution first after the
      * given initial delay, and subsequently with the given delay
      * between the termination of one execution and the commencement of
      * the next.
diff --git a/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java b/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java
index 4d63ffae4bb44..4fa9d00660bb0 100644
--- a/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java
+++ b/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java
@@ -41,9 +41,11 @@
  *
  * 

The {@code schedule} methods create tasks with various delays * and return a task object that can be used to cancel or check - * execution. The {@code scheduleAtFixedRate} and - * {@code scheduleWithFixedDelay} methods create and execute tasks - * that run periodically until cancelled. + * execution. When delays elapse, tasks are enabled for execution and + * behave in accord with other {@link ExecutorService} tasks, except + * that {@code scheduleAtFixedRate} and {@code scheduleWithFixedDelay} + * methods create and execute tasks that run periodically until + * cancelled. * *

Commands submitted using the {@link Executor#execute(Runnable)} * and {@link ExecutorService} {@code submit} methods are scheduled @@ -91,7 +93,7 @@ public interface ScheduledExecutorService extends ExecutorService { /** - * Submits a one-shot task that becomes enabled after the given delay. + * Submits a one-shot task that becomes enabled for execution after the given delay. * * @param command the task to execute * @param delay the time from now to delay execution @@ -107,7 +109,7 @@ public ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit); /** - * Submits a value-returning one-shot task that becomes enabled + * Submits a value-returning one-shot task that becomes enabled for execution * after the given delay. * * @param callable the function to execute @@ -123,7 +125,7 @@ public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit); /** - * Submits a periodic action that becomes enabled first after the + * Submits a periodic action that becomes enabled for execution first after the * given initial delay, and subsequently with the given period; * that is, executions will commence after * {@code initialDelay}, then {@code initialDelay + period}, then @@ -167,7 +169,7 @@ public ScheduledFuture scheduleAtFixedRate(Runnable command, TimeUnit unit); /** - * Submits a periodic action that becomes enabled first after the + * Submits a periodic action that becomes enabled for execution first after the * given initial delay, and subsequently with the given delay * between the termination of one execution and the commencement of * the next. diff --git a/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java b/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java index 94f40ccf6f516..23398aeae2813 100644 --- a/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java +++ b/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java @@ -57,7 +57,7 @@ * capabilities of {@link ThreadPoolExecutor} (which this class * extends) are required. * - *

Delayed tasks execute no sooner than they are enabled, but + *

Delayed tasks execute no sooner than they are enabled for execution, but * without any real-time guarantees about when, after they are * enabled, they will commence. Tasks scheduled for exactly the same * execution time are enabled in first-in-first-out (FIFO) order of @@ -568,7 +568,7 @@ public ScheduledFuture schedule(Callable callable, } /** - * Submits a periodic action that becomes enabled first after the + * Submits a periodic action that becomes enabled for execution first after the * given initial delay, and subsequently with the given period; * that is, executions will commence after * {@code initialDelay}, then {@code initialDelay + period}, then @@ -621,7 +621,7 @@ public ScheduledFuture scheduleAtFixedRate(Runnable command, } /** - * Submits a periodic action that becomes enabled first after the + * Submits a periodic action that becomes enabled for execution first after the * given initial delay, and subsequently with the given delay * between the termination of one execution and the commencement of * the next. diff --git a/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java b/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java index 3a8f37466374c..52989e8127730 100644 --- a/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java +++ b/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java @@ -162,8 +162,8 @@ * (this.subscription = subscription).request(1); * } * public void onNext(S item) { - * subscription.request(1); * submit(function.apply(item)); + * subscription.request(1); * } * public void onError(Throwable ex) { closeExceptionally(ex); } * public void onComplete() { close(); } @@ -602,9 +602,11 @@ public int offer(T item, long timeout, TimeUnit unit, /** * Unless already closed, issues {@link * Flow.Subscriber#onComplete() onComplete} signals to current - * subscribers, and disallows subsequent attempts to publish. - * Upon return, this method does NOT guarantee that all - * subscribers have yet completed. + * subscribers, and disallows subsequent attempts to publish. To + * ensure uniform ordering among subscribers, this method may + * await completion of in-progress offer. Upon return, this + * method does NOT guarantee that all subscribers have + * yet completed. */ public void close() { ReentrantLock lock = this.lock; diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java index 1c0c6d0afd070..a180cc8a1d5ad 100644 --- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java @@ -46,7 +46,7 @@ /** * A reflection-based utility that enables atomic updates to - * designated {@code volatile} reference fields of designated + * designated non-static {@code volatile} reference fields of designated * classes. This class is designed for use in atomic data structures * in which several reference fields of the same node are * independently subject to atomic updates. For example, a tree node From 519c981ffc0177e59dbd2411f46dcf59c4e89c08 Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Wed, 18 Jun 2025 13:37:01 -0400 Subject: [PATCH 03/12] Revert --- .../java/util/concurrent/Exchanger.java | 84 +++++++++++-------- 1 file changed, 47 insertions(+), 37 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/Exchanger.java b/src/java.base/share/classes/java/util/concurrent/Exchanger.java index e41f8c051a853..75de69b3e5283 100644 --- a/src/java.base/share/classes/java/util/concurrent/Exchanger.java +++ b/src/java.base/share/classes/java/util/concurrent/Exchanger.java @@ -276,10 +276,10 @@ static final class Node { int index; // Arena index Object item; // This thread's current item volatile Object match; // Item provided by releasing thread - final Thread thread; + volatile Thread parked; // Set to this thread when parked, else null Node() { index = -1; // initialize on first use - seed = (thread = Thread.currentThread()).threadId(); + seed = Thread.currentThread().threadId(); } } @@ -329,10 +329,10 @@ private final V xchg(V x, long deadline) Participant ps = participant; Object item = (x == null) ? ps : x; // translate nulls Node p = ps.get(); - p.item = item; int i = p.index; // if < 0, move int misses = 0; // ++ on collide, -- on spinout - Object v; // the match + Object offered = null; // for cleanup + Object v = null; outer: for (;;) { int b, m; Slot s; Node q; if ((m = (b = bound) & MMASK) == 0) // volatile read @@ -344,10 +344,11 @@ private final V xchg(V x, long deadline) } else if ((q = s.entry) != null) { // try release if (ENTRY.compareAndSet(s, q, null)) { + Thread w; v = q.item; q.match = item; - if (i == 0) - LockSupport.unpark(q.thread); + if (i == 0 && (w = q.parked) != null) + LockSupport.unpark(w); break; } else { // collision @@ -365,39 +366,47 @@ else if ((nb = (b + 1) & MMASK) < alen) { } } } - else if (ENTRY.compareAndSet(s, null, p)) { // try offer - boolean tryCancel = false; - for (long ns = 1L;;) { - if (p.match == null && !tryCancel) { - if ((deadline != 0L && - (ns = deadline - System.nanoTime()) <= 0L) || - Thread.currentThread().isInterrupted()) - tryCancel = true; // cancel unless match - else if (ncpu > 1 && - (i != 0 || // check for busy VTs - (!ForkJoinWorkerThread.hasKnownQueuedWork()))) { - for (int j = SPINS; p.match == null && j > 0; --j) - Thread.onSpinWait(); + else { // try offer + if (offered == null) + offered = p.item = item; + if (ENTRY.compareAndSet(s, null, p)) { + boolean tryCancel; // true if interrupted + Thread t = Thread.currentThread(); + if (!(tryCancel = t.isInterrupted()) && ncpu > 1 && + (i != 0 || // check for busy VTs + (!ForkJoinWorkerThread.hasKnownQueuedWork()))) { + for (int j = SPINS; j > 0; --j) { + if ((v = p.match) != null) { + MATCH.set(p, null); + break outer; // spin wait + } + Thread.onSpinWait(); } } - if ((v = MATCH.getAndSet(p, null)) != null) - break outer; - else if (!tryCancel && i == 0) { - if (deadline == 0L) - LockSupport.park(this); - else - LockSupport.parkNanos(this, ns); - } - else if (ENTRY.compareAndSet(s, p, null)) { // cancel - boolean interrupted = Thread.interrupted(); - if (interrupted || ns <= 0L) { - p.item = null; - if (interrupted) + for (long ns = 1L;;) { // block or cancel offer + if ((v = p.match) != null) { + MATCH.set(p, null); + break outer; + } + if (i == 0 && !tryCancel && + (deadline == 0L || + ((ns = deadline - System.nanoTime()) > 0L))) { + p.parked = t; // emable unpark and recheck + if (p.match == null) { + if (deadline == 0L) + LockSupport.park(this); + else + LockSupport.parkNanos(this, ns); + tryCancel = t.isInterrupted(); + } + p.parked = null; + } + else if (ENTRY.compareAndSet(s, p, null)) { // cancel + offered = p.item = null; + if (Thread.interrupted()) throw new InterruptedException(); - else + if (deadline != 0L && ns <= 0L) throw new TimeoutException(); - } - else { i = -1; // move and restart if (bound != b) misses = 0; // stale @@ -407,13 +416,14 @@ else if ((b & MMASK) != 0) { misses = 0; // try to shrink BOUND.compareAndSet(this, b, b - 1 + SEQ); } - break; + continue outer; } } } } } - p.item = null; // cleanup + if (offered != null) // cleanup + p.item = null; @SuppressWarnings("unchecked") V ret = (v == participant) ? null : (V)v; return ret; } From cadb2c91f6bd33d13a615d73b0f6af32450dbd0f Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Thu, 19 Jun 2025 07:03:39 -0400 Subject: [PATCH 04/12] Address review comments --- .../classes/java/util/concurrent/CompletionStage.java | 10 +++++----- .../share/classes/java/util/concurrent/Flow.java | 2 +- .../classes/java/util/concurrent/ForkJoinPool.java | 2 +- .../concurrent/atomic/AtomicIntegerFieldUpdater.java | 2 +- .../util/concurrent/atomic/AtomicLongFieldUpdater.java | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/CompletionStage.java b/src/java.base/share/classes/java/util/concurrent/CompletionStage.java index 0dc320aeee08a..2299046a6b174 100644 --- a/src/java.base/share/classes/java/util/concurrent/CompletionStage.java +++ b/src/java.base/share/classes/java/util/concurrent/CompletionStage.java @@ -99,8 +99,8 @@ * requiring its completion complete exceptionally as well, with a * {@link CompletionException} holding the exception as its * cause. This distinguishes exceptions in an action itself from those - * it depends on. If you want them handled in the same way, you might - * choose to catch {@link RuntimeException}. If a stage is dependent + * it depends on. If they are to be handled in the same way, instead + * catch {@link RuntimeException}. If a stage is dependent * on both of two stages, and both complete exceptionally, * then the CompletionException may correspond to either one of these * exceptions. If a stage is dependent on either of two @@ -150,9 +150,9 @@ * *

Memory consistency effects: Actions in a thread prior to the * submission of a computation producing a {@code CompletionStage} - * happen-before that computation begins. And actions taken by - * a {@code CompletionStage} happen-before actions of any - * dependent stage subsequent to its completion. + * happen-before that computation begins. And actions taken by + * {@code CompletionStage x} happen-before actions of any + * dependent stage subsequent to {@code x}'s completion. * * @param the type of values the stage produces or consumes * diff --git a/src/java.base/share/classes/java/util/concurrent/Flow.java b/src/java.base/share/classes/java/util/concurrent/Flow.java index d0590d08fbd48..16b2ba5e9d809 100644 --- a/src/java.base/share/classes/java/util/concurrent/Flow.java +++ b/src/java.base/share/classes/java/util/concurrent/Flow.java @@ -61,7 +61,7 @@ * only a single item, this class does not use buffering and ordering * control required in most implementations (for example {@link * SubmissionPublisher}), and omits some error processing needed to - * fully conform to ReactiveStream rules. + * fully conform to the Reactive Streams specification. * *

 {@code
  * class OneShotPublisher implements Publisher {
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 9262003a92deb..482fe3cf80136 100644
--- a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
+++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
@@ -140,7 +140,7 @@
  * tasks, as well as method {@link #submitWithTimeout} to cancel tasks
  * that take too long. The scheduled functions or actions may create
  * and invoke other {@linkplain ForkJoinTask ForkJoinTasks}. Delayed
- * actions become enabled for execution and behave as ordinary submitted
+ * actions become enabled for execution and behave as ordinary submitted
  * tasks when their delays elapse.  Scheduling methods return
  * {@linkplain ForkJoinTask ForkJoinTasks} that implement the {@link
  * ScheduledFuture} interface. Resource exhaustion encountered after
diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
index e01b3ec7d50f9..469b5bdba8c1e 100644
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
@@ -46,7 +46,7 @@
 
 /**
  * A reflection-based utility that enables atomic updates to
- * designated {@code volatile int} fields of designated classes.
+ * designated non-static {@code volatile int} fields of designated classes.
  * This class is designed for use in atomic data structures in which
  * several fields of the same node are independently subject to atomic
  * updates.
diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
index 57722f333711a..1005c122578d7 100644
--- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
@@ -46,7 +46,7 @@
 
 /**
  * A reflection-based utility that enables atomic updates to
- * designated {@code volatile long} fields of designated classes.
+ * designated non-static {@code volatile long} fields of designated classes.
  * This class is designed for use in atomic data structures in which
  * several fields of the same node are independently subject to atomic
  * updates.

From 18ea3e7b42c4b85c3ad7ea6c6858945479c89a6d Mon Sep 17 00:00:00 2001
From: Doug Lea 
Date: Thu, 19 Jun 2025 07:25:35 -0400
Subject: [PATCH 05/12] Add JDK-8353155 doc improvement

---
 .../share/classes/java/util/concurrent/RunnableFuture.java   | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/java.base/share/classes/java/util/concurrent/RunnableFuture.java b/src/java.base/share/classes/java/util/concurrent/RunnableFuture.java
index b6b088ae7cd82..8585cfe108297 100644
--- a/src/java.base/share/classes/java/util/concurrent/RunnableFuture.java
+++ b/src/java.base/share/classes/java/util/concurrent/RunnableFuture.java
@@ -47,8 +47,9 @@
  */
 public interface RunnableFuture extends Runnable, Future {
     /**
-     * Sets this Future to the result of its computation
-     * unless it has been cancelled.
+     * Sets this Future to the result of its computation unless it has
+     * been cancelled (or has already been invoked, in which case
+     * effects are undefined).
      */
     void run();
 }

From bd543fc50f4240d62a0d9e663ec9d50e8ddc47ca Mon Sep 17 00:00:00 2001
From: Doug Lea 
Date: Thu, 19 Jun 2025 07:39:06 -0400
Subject: [PATCH 06/12] Add JDK-8186959 docfix

---
 .../share/classes/java/util/concurrent/Executors.java         | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/java.base/share/classes/java/util/concurrent/Executors.java b/src/java.base/share/classes/java/util/concurrent/Executors.java
index ba7c2e1efeebe..ef3d634801090 100644
--- a/src/java.base/share/classes/java/util/concurrent/Executors.java
+++ b/src/java.base/share/classes/java/util/concurrent/Executors.java
@@ -306,7 +306,7 @@ public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFa
     }
 
     /**
-     * Creates a thread pool that can schedule commands to run after a
+     * Creates a fixed-size thread pool that can schedule commands to run after a
      * given delay, or to execute periodically.
      * @param corePoolSize the number of threads to keep in the pool,
      * even if they are idle
@@ -318,7 +318,7 @@ public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
     }
 
     /**
-     * Creates a thread pool that can schedule commands to run after a
+     * Creates a fixed-size thread pool that can schedule commands to run after a
      * given delay, or to execute periodically.
      * @param corePoolSize the number of threads to keep in the pool,
      * even if they are idle

From 4ef7649af4f35fdfa8d2cc918a3d1b7c1ff95cbc Mon Sep 17 00:00:00 2001
From: Doug Lea 
Date: Thu, 19 Jun 2025 07:54:13 -0400
Subject: [PATCH 07/12] Add JDK-8190889 docfix

---
 src/java.base/share/classes/java/util/concurrent/TimeUnit.java | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/java.base/share/classes/java/util/concurrent/TimeUnit.java b/src/java.base/share/classes/java/util/concurrent/TimeUnit.java
index f02aa9f593192..34f1577cad23b 100644
--- a/src/java.base/share/classes/java/util/concurrent/TimeUnit.java
+++ b/src/java.base/share/classes/java/util/concurrent/TimeUnit.java
@@ -398,6 +398,8 @@ else if (s == MICRO_SCALE)
      * @param obj the object to wait on
      * @param timeout the maximum time to wait. If less than
      * or equal to zero, do not wait at all.
+     * @throws  IllegalMonitorStateException  if the current thread is not
+     *               the owner of this object's monitor.
      * @throws InterruptedException if interrupted while waiting
      */
     public void timedWait(Object obj, long timeout)

From b10114e59e5b4b6ef3e6d789ea1f831a7568f3c1 Mon Sep 17 00:00:00 2001
From: Doug Lea 
Date: Thu, 19 Jun 2025 13:23:34 -0400
Subject: [PATCH 08/12] Add JDK-6317534 and JDK-6351533 doc improvements

---
 .../share/classes/java/util/concurrent/CyclicBarrier.java    | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java b/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java
index 87e498d9c247a..ca78c25462487 100644
--- a/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java
+++ b/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java
@@ -44,7 +44,10 @@
  * useful in programs involving a fixed sized party of threads that
  * must occasionally wait for each other. The barrier is called
  * cyclic because it can be re-used after the waiting threads
- * are released.
+ * are released. If you need support for variable numbers of parties
+ * per cycle, alternate actions on exceptions, termination control,
+ * contention control, or status monitoring, use the more flexible
+ * {@link Phaser} class.
  *
  * 

A {@code CyclicBarrier} supports an optional {@link Runnable} command * that is run once per barrier point, after the last thread in the party From c85698c7e8bc73ab8fb9182938d75d6805359b11 Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Thu, 19 Jun 2025 14:24:40 -0400 Subject: [PATCH 09/12] Add JDK-8195628 doc fix --- .../concurrent/locks/ReentrantReadWriteLock.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java b/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java index 3e0b293380f5f..4fce0455b3f78 100644 --- a/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java +++ b/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java @@ -734,9 +734,9 @@ protected ReadLock(ReentrantReadWriteLock lock) { * Acquires the read lock. * *

Acquires the read lock if the write lock is not held by - * another thread and returns immediately. + * any thread and returns immediately. * - *

If the write lock is held by another thread then + *

If the write lock is held by any thread then * the current thread becomes disabled for thread scheduling * purposes and lies dormant until the read lock has been acquired. */ @@ -749,9 +749,9 @@ public void lock() { * {@linkplain Thread#interrupt interrupted}. * *

Acquires the read lock if the write lock is not held - * by another thread and returns immediately. + * by any thread and returns immediately. * - *

If the write lock is held by another thread then the + *

If the write lock is held by any thread then the * current thread becomes disabled for thread scheduling * purposes and lies dormant until one of two things happens: * @@ -791,10 +791,10 @@ public void lockInterruptibly() throws InterruptedException { /** * Acquires the read lock only if the write lock is not held by - * another thread at the time of invocation. + * any thread at the time of invocation. * *

Acquires the read lock if the write lock is not held by - * another thread and returns immediately with the value + * any thread and returns immediately with the value * {@code true}. Even when this lock has been set to use a * fair ordering policy, a call to {@code tryLock()} * will immediately acquire the read lock if it is @@ -806,7 +806,7 @@ public void lockInterruptibly() throws InterruptedException { * tryLock(0, TimeUnit.SECONDS)} which is almost equivalent * (it also detects interruption). * - *

If the write lock is held by another thread then + *

If the write lock is held by any thread then * this method will return immediately with the value * {@code false}. * From 93ece642651290a351bcd9be04ef02833493c56a Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Thu, 19 Jun 2025 18:42:58 -0400 Subject: [PATCH 10/12] Adding JDK-8333172 to doc improvements --- .../atomic/AtomicIntegerFieldUpdater.java | 9 ++++--- .../atomic/AtomicLongFieldUpdater.java | 9 ++++--- .../atomic/AtomicReferenceFieldUpdater.java | 27 +++++++++++++++---- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java index 469b5bdba8c1e..f947eb4f7db88 100644 --- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java @@ -46,10 +46,11 @@ /** * A reflection-based utility that enables atomic updates to - * designated non-static {@code volatile int} fields of designated classes. - * This class is designed for use in atomic data structures in which - * several fields of the same node are independently subject to atomic - * updates. + * designated non-static {@code volatile int} fields of designated + * classes, providing a subset of the functionality of class {@link + * VarHandle} that should be used instead. This class is designed for + * use in atomic data structures in which several fields of the same + * node are independently subject to atomic updates. * *

Note that the guarantees of the {@code compareAndSet} * method in this class are weaker than in other atomic classes. diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java index 1005c122578d7..b31a8edf53a46 100644 --- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java @@ -46,10 +46,11 @@ /** * A reflection-based utility that enables atomic updates to - * designated non-static {@code volatile long} fields of designated classes. - * This class is designed for use in atomic data structures in which - * several fields of the same node are independently subject to atomic - * updates. + * designated non-static {@code volatile long} fields of designated + * classes, providing a subset of the functionality of class {@link + * VarHandle} that should be used instead. This class is designed for + * use in atomic data structures in which several fields of the same + * node are independently subject to atomic updates. * *

Note that the guarantees of the {@code compareAndSet} * method in this class are weaker than in other atomic classes. diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java index a180cc8a1d5ad..00220145d419c 100644 --- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java @@ -46,11 +46,12 @@ /** * A reflection-based utility that enables atomic updates to - * designated non-static {@code volatile} reference fields of designated - * classes. This class is designed for use in atomic data structures - * in which several reference fields of the same node are - * independently subject to atomic updates. For example, a tree node - * might be declared as + * designated non-static {@code volatile} reference fields of + * designated classes, providing a subset of the functionality of + * class {@link VarHandle} that should be used instead. This class + * may be used in atomic data structures in which several reference + * fields of the same node are independently subject to atomic + * updates. For example, a tree node might be declared as * *

 {@code
  * class Node {
@@ -68,6 +69,22 @@
  *   // ... and so on
  * }}
* + * However, it is preferable to use {@link VarHandle}: + *
 {@code
+ * class Node {
+ *   private volatile Node left, right;
+ *
+ *   private static final VarHandle LEFT = MethodHandles.lookup().
+ *      findVarHandle(Node.class, "left", Node.class);
+ *   private static final VarHandle RIGHT = MethodHandles.lookup().
+ *      findVarHandle(Node.class, "right", Node.class);
+ *   Node getLeft() { return left; }
+ *   boolean compareAndSetLeft(Node expect, Node update) {
+ *     return LEFT.compareAndSet(this, expect, update);
+ *   }
+ *   // ... and so on
+ * }}
+ * *

Note that the guarantees of the {@code compareAndSet} * method in this class are weaker than in other atomic classes. * Because this class cannot ensure that all uses of the field From 044d8dcdd1b29877ce9bf71fbfd4ad5a48e5cc12 Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Fri, 20 Jun 2025 09:56:12 -0400 Subject: [PATCH 11/12] Address review comments; add JDK-6374942 --- .../concurrent/ScheduledExecutorService.java | 2 +- .../util/concurrent/SubmissionPublisher.java | 2 +- .../java/util/concurrent/TimeUnit.java | 2 +- .../atomic/AtomicReferenceFieldUpdater.java | 28 +++++++++++-------- .../locks/ReentrantReadWriteLock.java | 2 +- .../java/util/concurrent/package-info.java | 4 ++- 6 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java b/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java index 4fa9d00660bb0..034d98687c257 100644 --- a/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java +++ b/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java @@ -40,7 +40,7 @@ * delay, or to execute periodically. * *

The {@code schedule} methods create tasks with various delays - * and return a task object that can be used to cancel or check + * and return {@link ScheduledFuture} objects that can be used to cancel or check * execution. When delays elapse, tasks are enabled for execution and * behave in accord with other {@link ExecutorService} tasks, except * that {@code scheduleAtFixedRate} and {@code scheduleWithFixedDelay} diff --git a/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java b/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java index 52989e8127730..f793d2bcabdf2 100644 --- a/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java +++ b/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java @@ -604,7 +604,7 @@ public int offer(T item, long timeout, TimeUnit unit, * Flow.Subscriber#onComplete() onComplete} signals to current * subscribers, and disallows subsequent attempts to publish. To * ensure uniform ordering among subscribers, this method may - * await completion of in-progress offer. Upon return, this + * await completion of in-progress offers. Upon return, this * method does NOT guarantee that all subscribers have * yet completed. */ diff --git a/src/java.base/share/classes/java/util/concurrent/TimeUnit.java b/src/java.base/share/classes/java/util/concurrent/TimeUnit.java index 34f1577cad23b..d116fb9b22bcc 100644 --- a/src/java.base/share/classes/java/util/concurrent/TimeUnit.java +++ b/src/java.base/share/classes/java/util/concurrent/TimeUnit.java @@ -399,7 +399,7 @@ else if (s == MICRO_SCALE) * @param timeout the maximum time to wait. If less than * or equal to zero, do not wait at all. * @throws IllegalMonitorStateException if the current thread is not - * the owner of this object's monitor. + * the owner of the object's monitor. * @throws InterruptedException if interrupted while waiting */ public void timedWait(Object obj, long timeout) diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java index 00220145d419c..d29c2bac0d0b6 100644 --- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java @@ -71,19 +71,23 @@ * * However, it is preferable to use {@link VarHandle}: *

 {@code
+ * import java.lang.invoke.VarHandle;
+ * import java.lang.invoke.MethodHandles;
  * class Node {
- *   private volatile Node left, right;
- *
- *   private static final VarHandle LEFT = MethodHandles.lookup().
- *      findVarHandle(Node.class, "left", Node.class);
- *   private static final VarHandle RIGHT = MethodHandles.lookup().
- *      findVarHandle(Node.class, "right", Node.class);
- *   Node getLeft() { return left; }
- *   boolean compareAndSetLeft(Node expect, Node update) {
- *     return LEFT.compareAndSet(this, expect, update);
- *   }
- *   // ... and so on
- * }}
+ * private volatile Node left, right; + * private static final VarHandle LEFT, RIGHT; + * Node getLeft() { return left; } + * boolean compareAndSetLeft(Node expect, Node update) { + * return LEFT.compareAndSet(this, expect, update); + * } + * // ... and so on + * static { try { + * MethodHandles.Lookup l = MethodHandles.lookup(); + * LEFT = l.findVarHandle(Node.class, "left", Node.class); + * RIGHT = l.findVarHandle(Node.class, "right", Node.class); + * } catch (ReflectiveOperationException e) { + * throw new ExceptionInInitializerError(e); + * }}}
* *

Note that the guarantees of the {@code compareAndSet} * method in this class are weaker than in other atomic classes. diff --git a/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java b/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java index 4fce0455b3f78..b5dd95eb9d919 100644 --- a/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java +++ b/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java @@ -791,7 +791,7 @@ public void lockInterruptibly() throws InterruptedException { /** * Acquires the read lock only if the write lock is not held by - * any thread at the time of invocation. + * another thread at the time of invocation. * *

Acquires the read lock if the write lock is not held by * any thread and returns immediately with the value diff --git a/src/java.base/share/classes/java/util/concurrent/package-info.java b/src/java.base/share/classes/java/util/concurrent/package-info.java index dd0c8f79bc024..f237017799d9f 100644 --- a/src/java.base/share/classes/java/util/concurrent/package-info.java +++ b/src/java.base/share/classes/java/util/concurrent/package-info.java @@ -222,7 +222,9 @@ *

  • they are guaranteed to traverse elements as they existed upon * construction exactly once, and may (but are not guaranteed to) * reflect any modifications subsequent to construction. - * + *
  • These properties extend to other iteration-based + * operations. In particular, {@link Object#equals} is almost never + * useful unless both collections are known to be quiescent. * *

    Memory Consistency Properties

    * From 26d96b88e3ce8fe1143ecfc3f5a781e4dd4a6985 Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Fri, 20 Jun 2025 11:48:53 -0400 Subject: [PATCH 12/12] Fix ARFU type; add JDK-7176957 --- .../share/classes/java/util/concurrent/ExecutorService.java | 4 +++- .../util/concurrent/atomic/AtomicReferenceFieldUpdater.java | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/ExecutorService.java b/src/java.base/share/classes/java/util/concurrent/ExecutorService.java index 0d4acf8913e04..f899b56b28883 100644 --- a/src/java.base/share/classes/java/util/concurrent/ExecutorService.java +++ b/src/java.base/share/classes/java/util/concurrent/ExecutorService.java @@ -56,7 +56,9 @@ * *

    Method {@code submit} extends base method {@link * Executor#execute(Runnable)} by creating and returning a {@link Future} - * that can be used to cancel execution and/or wait for completion. + * that can be used to cancel execution and/or wait for completion; + * also reporting exceptions that would otherwise be uncaught + * using method {@code execute}. * Methods {@code invokeAny} and {@code invokeAll} perform the most * commonly useful forms of bulk execution, executing a collection of * tasks and then waiting for at least one, or all, to diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java index d29c2bac0d0b6..e3ca4830d5a21 100644 --- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java @@ -87,7 +87,7 @@ * RIGHT = l.findVarHandle(Node.class, "right", Node.class); * } catch (ReflectiveOperationException e) { * throw new ExceptionInInitializerError(e); - * }}}

  • + * }}}} * *

    Note that the guarantees of the {@code compareAndSet} * method in this class are weaker than in other atomic classes.