代码拉取完成,页面将自动刷新
From 20109e1a7f9941662abd5069d30ad693c181f415 Mon Sep 17 00:00:00 2001
Date: Fri, 22 Jan 2021 11:33:53 +0800
Subject: Backport of JDK-8191483
summary: AbstractQueuedSynchronizer cancel/cancel race
LLT:
Bug url: https://bugs.openjdk.java.net/browse/JDK-8191483
---
.../locks/AbstractQueuedLongSynchronizer.java | 34 +++++++++++--------
.../locks/AbstractQueuedSynchronizer.java | 34 +++++++++++--------
2 files changed, 40 insertions(+), 28 deletions(-)
diff --git a/jdk/src/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java b/jdk/src/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
index 47fdbfb94..8699fc9b8 100644
--- a/jdk/src/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
+++ b/jdk/src/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
@@ -531,7 +531,9 @@ public abstract class AbstractQueuedLongSynchronizer
// predNext is the apparent node to unsplice. CASes below will
// fail if not, in which case, we lost race vs another cancel
- // or signal, so no further action is necessary.
+ // or signal, so no further action is necessary, although with
+ // a possibility that a cancelled node may transiently remain
+ // reachable.
Node predNext = pred.next;
// Can use unconditional write instead of CAS here.
@@ -1131,13 +1133,13 @@ public abstract class AbstractQueuedLongSynchronizer
* at any time, a {@code true} return does not guarantee that any
* other thread will ever acquire.
*
- * <p>In this implementation, this operation returns in
- * constant time.
- *
* @return {@code true} if there may be other threads waiting to acquire
*/
public final boolean hasQueuedThreads() {
- return head != tail;
+ for (Node p = tail, h = head; p != h && p != null; p = p.prev)
+ if (p.waitStatus <= 0)
+ return true;
+ return false;
}
/**
@@ -1288,17 +1290,21 @@ public abstract class AbstractQueuedLongSynchronizer
* @since 1.7
*/
public final boolean hasQueuedPredecessors() {
- // The correctness of this depends on head being initialized
- // before tail and on head.next being accurate if the current
- // thread is first in queue.
- Node t = tail; // Read fields in reverse initialization order
- Node h = head;
- Node s;
- return h != t &&
- ((s = h.next) == null || s.thread != Thread.currentThread());
+ Node h, s;
+ if ((h = head) != null) {
+ if ((s = h.next) == null || s.waitStatus > 0) {
+ s = null; // traverse in case of concurrent cancellation
+ for (Node p = tail; p != h && p != null; p = p.prev) {
+ if (p.waitStatus <= 0)
+ s = p;
+ }
+ }
+ if (s != null && s.thread != Thread.currentThread())
+ return true;
+ }
+ return false;
}
-
// Instrumentation and monitoring methods
/**
diff --git a/jdk/src/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java b/jdk/src/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
index dce35765d..9088e5894 100644
--- a/jdk/src/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
+++ b/jdk/src/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
@@ -753,7 +753,9 @@ public abstract class AbstractQueuedSynchronizer
// predNext is the apparent node to unsplice. CASes below will
// fail if not, in which case, we lost race vs another cancel
- // or signal, so no further action is necessary.
+ // or signal, so no further action is necessary, although with
+ // a possibility that a cancelled node may transiently remain
+ // reachable.
Node predNext = pred.next;
// Can use unconditional write instead of CAS here.
@@ -1353,13 +1355,13 @@ public abstract class AbstractQueuedSynchronizer
* at any time, a {@code true} return does not guarantee that any
* other thread will ever acquire.
*
- * <p>In this implementation, this operation returns in
- * constant time.
- *
* @return {@code true} if there may be other threads waiting to acquire
*/
public final boolean hasQueuedThreads() {
- return head != tail;
+ for (Node p = tail, h = head; p != h && p != null; p = p.prev)
+ if (p.waitStatus <= 0)
+ return true;
+ return false;
}
/**
@@ -1510,17 +1512,21 @@ public abstract class AbstractQueuedSynchronizer
* @since 1.7
*/
public final boolean hasQueuedPredecessors() {
- // The correctness of this depends on head being initialized
- // before tail and on head.next being accurate if the current
- // thread is first in queue.
- Node t = tail; // Read fields in reverse initialization order
- Node h = head;
- Node s;
- return h != t &&
- ((s = h.next) == null || s.thread != Thread.currentThread());
+ Node h, s;
+ if ((h = head) != null) {
+ if ((s = h.next) == null || s.waitStatus > 0) {
+ s = null; // traverse in case of concurrent cancellation
+ for (Node p = tail; p != h && p != null; p = p.prev) {
+ if (p.waitStatus <= 0)
+ s = p;
+ }
+ }
+ if (s != null && s.thread != Thread.currentThread())
+ return true;
+ }
+ return false;
}
-
// Instrumentation and monitoring methods
/**
--
2.19.0
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。