23 Star 19 Fork 75

src-openEuler / openjdk-1.8.0

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
8191483.patch 5.70 KB
一键复制 编辑 原始数据 按行查看 历史
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
1
https://gitee.com/src-openeuler/openjdk-1.8.0.git
git@gitee.com:src-openeuler/openjdk-1.8.0.git
src-openeuler
openjdk-1.8.0
openjdk-1.8.0
master

搜索帮助