⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 abstractqueuedlongsynchronizer.java

📁 JAVA 所有包
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
     *     * <p>In this implementation, this operation normally returns in     * constant time, but may iterate upon contention if other threads are     * concurrently modifying the queue.     *     * @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();    }    /**     * Version of getFirstQueuedThread called when fastpath fails     */    private Thread fullGetFirstQueuedThread() {        /*         * The first node is normally h.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;        if (((h = head) != null && (s = h.next) != null &&             s.prev == head && (st = s.thread) != null) ||            ((h = head) != null && (s = h.next) != null &&             s.prev == head && (st = s.thread) != 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.         */        Node t = tail;        Thread firstThread = null;        while (t != null && t != head) {            Thread tt = t.thread;            if (tt != null)                firstThread = tt;            t = t.prev;        }        return firstThread;    }    /**     * Returns true if the given thread is currently queued.     *     * <p>This implementation traverses the queue to determine     * presence of the given thread.     *     * @param thread the thread     * @return {@code true} if the given thread is on the queue     * @throws NullPointerException if the thread is null     */    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)                return true;        return false;    }    /**     * Return {@code true} if the apparent first queued thread, if one     * exists, is not waiting in exclusive mode. Used only as a heuristic     * in ReentrantReadWriteLock.     */    final boolean apparentlyFirstQueuedIsExclusive() {        Node h, s;        return ((h = head) != null && (s = h.next) != null &&                s.nextWaiter != Node.SHARED);    }    /**     * Return {@code true} if the queue is empty or if the given thread     * is at the head of the queue. This is reliable only if     * <tt>current</tt> is actually Thread.currentThread() of caller.     */    final boolean isFirst(Thread current) {        Node h, s;        return ((h = head) == null ||                ((s = h.next) != null && s.thread == current) ||                fullIsFirst(current));    }    final boolean fullIsFirst(Thread current) {        // same idea as fullGetFirstQueuedThread        Node h, s;        Thread firstThread = null;        if (((h = head) != null && (s = h.next) != null &&             s.prev == head && (firstThread = s.thread) != null))            return firstThread == current;        Node t = tail;        while (t != null && t != head) {            Thread tt = t.thread;            if (tt != null)                firstThread = tt;            t = t.prev;        }        return firstThread == current || firstThread == null;    }    // Instrumentation and monitoring methods    /**     * Returns an estimate of the number of threads waiting to     * acquire.  The value is only an estimate because the number of     * threads may change dynamically while this method traverses     * internal data structures.  This method is designed for use in     * monitoring system state, not for synchronization     * control.     *     * @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)                ++n;        }        return n;    }    /**     * Returns a collection containing threads that may be waiting to     * acquire.  Because the actual set of threads may change     * dynamically while constructing this result, the returned     * collection is only a best-effort estimate.  The elements of the     * returned collection are in no particular order.  This method is     * designed to facilitate construction of subclasses that provide     * more extensive monitoring facilities.     *     * @return the collection of threads     */    public final Collection<Thread> getQueuedThreads() {        ArrayList<Thread> list = new ArrayList<Thread>();        for (Node p = tail; p != null; p = p.prev) {            Thread t = p.thread;            if (t != null)                list.add(t);        }        return list;    }    /**     * Returns a collection containing threads that may be waiting to     * acquire in exclusive mode. This has the same properties     * as {@link #getQueuedThreads} except that it only returns     * those threads waiting due to an exclusive acquire.     *     * @return the collection of threads     */    public final Collection<Thread> getExclusiveQueuedThreads() {        ArrayList<Thread> list = new ArrayList<Thread>();        for (Node p = tail; p != null; p = p.prev) {            if (!p.isShared()) {                Thread t = p.thread;                if (t != null)                    list.add(t);            }        }        return list;    }    /**     * Returns a collection containing threads that may be waiting to     * acquire in shared mode. This has the same properties     * as {@link #getQueuedThreads} except that it only returns     * those threads waiting due to a shared acquire.     *     * @return the collection of threads     */    public final Collection<Thread> getSharedQueuedThreads() {        ArrayList<Thread> list = new ArrayList<Thread>();        for (Node p = tail; p != null; p = p.prev) {            if (p.isShared()) {                Thread t = p.thread;                if (t != null)                    list.add(t);            }        }        return list;    }    /**     * Returns a string identifying this synchronizer, as well as its state.     * The state, in brackets, includes the String {@code "State ="}     * followed by the current value of {@link #getState}, and either     * {@code "nonempty"} or {@code "empty"} depending on whether the     * queue is empty.     *     * @return a string identifying this synchronizer, as well as its state     */    public String toString() {        long s = getState();        String q  = hasQueuedThreads()? "non" : "";        return super.toString() +            "[State = " + s + ", " + q + "empty queue]";    }    // Internal support methods for Conditions    /**     * Returns true if a node, always one that was initially placed on     * a condition queue, is now waiting to reacquire on sync queue.     * @param node the node     * @return true if is reacquiring     */    final boolean isOnSyncQueue(Node node) {        if (node.waitStatus == Node.CONDITION || node.prev == null)            return false;        if (node.next != null) // If has successor, it must be on queue            return true;        /*         * node.prev can be non-null, but not yet on queue because         * the CAS to place it on queue can fail. So we have to         * traverse from tail to make sure it actually made it.  It         * will always be near the tail in calls to this method, and         * unless the CAS failed (which is unlikely), it will be         * there, so we hardly ever traverse much.         */        return findNodeFromTail(node);    }    /**     * Returns true if node is on sync queue by searching backwards from tail.     * Called only when needed by isOnSyncQueue.     * @return true if present     */    private boolean findNodeFromTail(Node node) {        Node t = tail;        for (;;) {            if (t == node)                return true;            if (t == null)                return false;            t = t.prev;        }    }    /**     * Transfers a node from a condition queue onto sync queue.     * Returns true if successful.     * @param node the node     * @return true if successfully transferred (else the node was     * cancelled before signal).     */    final boolean transferForSignal(Node node) {        /*         * If cannot change waitStatus, the node has been cancelled.         */        if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))            return false;        /*         * Splice onto queue and try to set waitStatus of predecessor to         * indicate that thread is (probably) waiting. If cancelled or         * attempt to set waitStatus fails, wake up to resync (in which         * case the waitStatus can be transiently and harmlessly wrong).         */        Node p = enq(node);        int c = p.waitStatus;        if (c > 0 || !compareAndSetWaitStatus(p, c, Node.SIGNAL))            LockSupport.unpark(node.thread);        return true;    }    /**     * Transfers node, if necessary, to sync queue after a cancelled     * wait. Returns true if thread was cancelled before being     * signalled.     * @param current the waiting thread     * @param node its node     * @return true if cancelled before the node was signalled.     */    final boolean transferAfterCancelledWait(Node node) {        if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {            enq(node);            return true;        }        /*         * If we lost out to a signal(), then we can't proceed         * until it finishes its enq().  Cancelling during an         * incomplete transfer is both rare and transient, so just         * spin.         */        while (!isOnSyncQueue(node))            Thread.yield();        return false;    }    /**     * Invokes release with current state value; returns saved state.     * Cancels node and throws exception on failure.     * @param node the condition node for this wait     * @return previous sync state     */    final long fullyRelease(Node node) {        try {            long savedState = getState();            if (release(savedState))                return savedState;        } catch (RuntimeException ex) {            node.waitStatus = Node.CANCELLED;            throw ex;        }        // reach here if release fails        node.waitStatus = Node.CANCELLED;        throw new IllegalMonitorStateException();    }    // Instrumentation methods for conditions    /**     * Queries whether the given ConditionObject     * uses this synchronizer as its lock.     *     * @param condition the condition     * @return <tt>true</tt> if owned     * @throws NullPointerException if the condition is null     */    public final boolean owns(ConditionObject condition) {        if (condition == null)            throw new NullPointerException();        return condition.isOwnedBy(this);    }    /**     * Queries whether any threads are waiting on the given condition     * associated with this synchronizer. Note that because timeouts     * and interrupts may occur at any time, a <tt>true</tt> return     * does not guarantee that a future <tt>signal</tt> will awaken     * any threads.  This method is designed primarily for use in

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -