< prev index next >

src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java

Print this page

        

@@ -40,10 +40,12 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
 import java.util.concurrent.TimeUnit;
 
+import jdk.internal.misc.Strands;
+
 /**
  * Provides a framework for implementing blocking locks and related
  * synchronizers (semaphores, events, etc) that rely on
  * first-in-first-out (FIFO) wait queues.  This class is designed to
  * be a useful basis for most kinds of synchronizers that rely on a

@@ -472,14 +474,14 @@
          * easier for isOnSyncQueue.
          */
         volatile Node next;
 
         /**
-         * The thread that enqueued this node.  Initialized on
+         * The strand that enqueued this node.  Initialized on
          * construction and nulled out after use.
          */
-        volatile Thread thread;
+        volatile Object strand;
 
         /**
          * Link to next node waiting on condition, or the special
          * value SHARED.  Because condition queues are accessed only
          * when holding in exclusive mode, we just need a simple

@@ -517,17 +519,17 @@
         Node() {}
 
         /** Constructor used by addWaiter. */
         Node(Node nextWaiter) {
             this.nextWaiter = nextWaiter;
-            THREAD.set(this, Thread.currentThread());
+            STRAND.set(this, Strands.currentStrand());
         }
 
         /** Constructor used by addConditionWaiter. */
         Node(int waitStatus) {
             WAITSTATUS.set(this, waitStatus);
-            THREAD.set(this, Thread.currentThread());
+            STRAND.set(this, Strands.currentStrand());
         }
 
         /** CASes waitStatus field. */
         final boolean compareAndSetWaitStatus(int expect, int update) {
             return WAITSTATUS.compareAndSet(this, expect, update);

@@ -543,18 +545,18 @@
         }
 
         // VarHandle mechanics
         private static final VarHandle NEXT;
         private static final VarHandle PREV;
-        private static final VarHandle THREAD;
+        private static final VarHandle STRAND;
         private static final VarHandle WAITSTATUS;
         static {
             try {
                 MethodHandles.Lookup l = MethodHandles.lookup();
                 NEXT = l.findVarHandle(Node.class, "next", Node.class);
                 PREV = l.findVarHandle(Node.class, "prev", Node.class);
-                THREAD = l.findVarHandle(Node.class, "thread", Thread.class);
+                STRAND = l.findVarHandle(Node.class, "strand", Object.class);
                 WAITSTATUS = l.findVarHandle(Node.class, "waitStatus", int.class);
             } catch (ReflectiveOperationException e) {
                 throw new ExceptionInInitializerError(e);
             }
         }

@@ -671,11 +673,11 @@
      *
      * @param node the node
      */
     private void setHead(Node node) {
         head = node;
-        node.thread = null;
+        node.strand = null;
         node.prev = null;
     }
 
     /**
      * Wakes up node's successor, if one exists.

@@ -704,11 +706,11 @@
             for (Node p = tail; p != node && p != null; p = p.prev)
                 if (p.waitStatus <= 0)
                     s = p;
         }
         if (s != null)
-            LockSupport.unpark(s.thread);
+            LockSupport.unpark(s.strand);
     }
 
     /**
      * Release action for shared mode -- signals successor and ensures
      * propagation. (Note: For exclusive mode, release just amounts

@@ -789,11 +791,11 @@
     private void cancelAcquire(Node node) {
         // Ignore if node doesn't exist
         if (node == null)
             return;
 
-        node.thread = null;
+        node.strand = null;
 
         // Skip cancelled predecessors
         Node pred = node.prev;
         while (pred.waitStatus > 0)
             node.prev = pred = pred.prev;

@@ -818,11 +820,11 @@
             // so it will get one. Otherwise wake it up to propagate.
             int ws;
             if (pred != head &&
                 ((ws = pred.waitStatus) == Node.SIGNAL ||
                  (ws <= 0 && pred.compareAndSetWaitStatus(ws, Node.SIGNAL))) &&
-                pred.thread != null) {
+                pred.strand != null) {
                 Node next = node.next;
                 if (next != null && next.waitStatus <= 0)
                     pred.compareAndSetNext(predNext, next);
             } else {
                 unparkSuccessor(node);

@@ -1427,48 +1429,49 @@
      * @return the first (longest-waiting) thread in the queue, or
      *         {@code null} if no threads are currently queued
      */
     public final Thread getFirstQueuedThread() {
         // handle only fast path, else relay
-        return (head == tail) ? null : fullGetFirstQueuedThread();
+        // FIXME: may throw ClassCastException
+        return (head == tail) ? null : (Thread) fullGetFirstQueuedStrand();
     }
 
     /**
-     * Version of getFirstQueuedThread called when fastpath fails.
+     * Version of getFirstQueuedStrand called when fastpath fails.
      */
-    private Thread fullGetFirstQueuedThread() {
+    private Object fullGetFirstQueuedStrand() {
         /*
          * The first node is normally head.next. Try to get its
          * thread field, ensuring consistent reads: If thread
          * field is nulled out or s.prev is no longer head, then
          * some other thread(s) concurrently performed setHead in
          * between some of our reads. We try this twice before
          * resorting to traversal.
          */
         Node h, s;
-        Thread st;
+        Object st;
         if (((h = head) != null && (s = h.next) != null &&
-             s.prev == head && (st = s.thread) != null) ||
+             s.prev == head && (st = s.strand) != null) ||
             ((h = head) != null && (s = h.next) != null &&
-             s.prev == head && (st = s.thread) != null))
+             s.prev == head && (st = s.strand) != null))
             return st;
 
         /*
          * Head's next field might not have been set yet, or may have
          * been unset after setHead. So we must check to see if tail
          * is actually first node. If not, we continue on, safely
          * traversing from tail back to head to find first,
          * guaranteeing termination.
          */
 
-        Thread firstThread = null;
+        Object firstStrand= null;
         for (Node p = tail; p != null && p != head; p = p.prev) {
-            Thread t = p.thread;
-            if (t != null)
-                firstThread = t;
+            Object strand = p.strand;
+            if (strand != null)
+                firstStrand = strand;
         }
-        return firstThread;
+        return firstStrand;
     }
 
     /**
      * Returns true if the given thread is currently queued.
      *

@@ -1481,11 +1484,11 @@
      */
     public final boolean isQueued(Thread thread) {
         if (thread == null)
             throw new NullPointerException();
         for (Node p = tail; p != null; p = p.prev)
-            if (p.thread == thread)
+            if (p.strand == thread)
                 return true;
         return false;
     }
 
     /**

@@ -1500,11 +1503,11 @@
     final boolean apparentlyFirstQueuedIsExclusive() {
         Node h, s;
         return (h = head) != null &&
             (s = h.next)  != null &&
             !s.isShared()         &&
-            s.thread != null;
+            s.strand != null;
     }
 
     /**
      * Queries whether any threads have been waiting to acquire longer
      * than the current thread.

@@ -1556,11 +1559,11 @@
                 for (Node p = tail; p != h && p != null; p = p.prev) {
                     if (p.waitStatus <= 0)
                         s = p;
                 }
             }
-            if (s != null && s.thread != Thread.currentThread())
+            if (s != null && s.strand != Strands.currentStrand())
                 return true;
         }
         return false;
     }
 

@@ -1576,11 +1579,11 @@
      * @return the estimated number of threads waiting to acquire
      */
     public final int getQueueLength() {
         int n = 0;
         for (Node p = tail; p != null; p = p.prev) {
-            if (p.thread != null)
+            if (p.strand != null)
                 ++n;
         }
         return n;
     }
 

@@ -1596,13 +1599,13 @@
      * @return the collection of threads
      */
     public final Collection<Thread> getQueuedThreads() {
         ArrayList<Thread> list = new ArrayList<>();
         for (Node p = tail; p != null; p = p.prev) {
-            Thread t = p.thread;
-            if (t != null)
-                list.add(t);
+            Object s = p.strand;
+            if (s instanceof Thread)
+                list.add((Thread)s);
         }
         return list;
     }
 
     /**

@@ -1615,13 +1618,13 @@
      */
     public final Collection<Thread> getExclusiveQueuedThreads() {
         ArrayList<Thread> list = new ArrayList<>();
         for (Node p = tail; p != null; p = p.prev) {
             if (!p.isShared()) {
-                Thread t = p.thread;
-                if (t != null)
-                    list.add(t);
+                Object s = p.strand;
+                if (s instanceof Thread)
+                    list.add((Thread)s);
             }
         }
         return list;
     }
 

@@ -1635,13 +1638,13 @@
      */
     public final Collection<Thread> getSharedQueuedThreads() {
         ArrayList<Thread> list = new ArrayList<>();
         for (Node p = tail; p != null; p = p.prev) {
             if (p.isShared()) {
-                Thread t = p.thread;
-                if (t != null)
-                    list.add(t);
+                Object s = p.strand;
+                if (s instanceof Thread)
+                    list.add((Thread)s);
             }
         }
         return list;
     }
 

@@ -1724,11 +1727,11 @@
          * case the waitStatus can be transiently and harmlessly wrong).
          */
         Node p = enq(node);
         int ws = p.waitStatus;
         if (ws > 0 || !p.compareAndSetWaitStatus(ws, Node.SIGNAL))
-            LockSupport.unpark(node.thread);
+            LockSupport.unpark(node.strand);
         return true;
     }
 
     /**
      * Transfers node, if necessary, to sync queue after a cancelled wait.

@@ -2285,13 +2288,13 @@
             if (!isHeldExclusively())
                 throw new IllegalMonitorStateException();
             ArrayList<Thread> list = new ArrayList<>();
             for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
                 if (w.waitStatus == Node.CONDITION) {
-                    Thread t = w.thread;
-                    if (t != null)
-                        list.add(t);
+                    Object s = w.strand;
+                    if (s != null)
+                        list.add((Thread)s);
                 }
             }
             return list;
         }
     }
< prev index next >