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

📄 abstractqueuedlongsynchronizer.java

📁 JAVA 所有包
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
    private Node addWaiter(Node mode) {        Node node = new Node(Thread.currentThread(), mode);        // Try the fast path of enq; backup to full enq on failure        Node pred = tail;        if (pred != null) {            node.prev = pred;            if (compareAndSetTail(pred, node)) {                pred.next = node;                return node;            }        }        enq(node);        return node;    }    /**     * Sets head of queue to be node, thus dequeuing. Called only by     * acquire methods.  Also nulls out unused fields for sake of GC     * and to suppress unnecessary signals and traversals.     *     * @param node the node     */    private void setHead(Node node) {        head = node;        node.thread = null;        node.prev = null;    }    /**     * Wakes up node's successor, if one exists.     *     * @param node the node     */    private void unparkSuccessor(Node node) {        /*         * Try to clear status in anticipation of signalling.  It is         * OK if this fails or if status is changed by waiting thread.         */        compareAndSetWaitStatus(node, Node.SIGNAL, 0);        /*         * Thread to unpark is held in successor, which is normally         * just the next node.  But if cancelled or apparently null,         * traverse backwards from tail to find the actual         * non-cancelled successor.         */        Node s = node.next;        if (s == null || s.waitStatus > 0) {            s = null;            for (Node t = tail; t != null && t != node; t = t.prev)                if (t.waitStatus <= 0)                    s = t;        }        if (s != null)            LockSupport.unpark(s.thread);    }    /**     * Sets head of queue, and checks if successor may be waiting     * in shared mode, if so propagating if propagate > 0.     *     * @param pred the node holding waitStatus for node     * @param node the node     * @param propagate the return value from a tryAcquireShared     */    private void setHeadAndPropagate(Node node, long propagate) {        setHead(node);        if (propagate > 0 && node.waitStatus != 0) {            /*             * Don't bother fully figuring out successor.  If it             * looks null, call unparkSuccessor anyway to be safe.             */            Node s = node.next;            if (s == null || s.isShared())                unparkSuccessor(node);        }    }    // Utilities for various versions of acquire    /**     * Cancels an ongoing attempt to acquire.     *     * @param node the node     */    private void cancelAcquire(Node node) {        if (node != null) { // Ignore if node doesn't exist            node.thread = null;            // Can use unconditional write instead of CAS here            node.waitStatus = Node.CANCELLED;            unparkSuccessor(node);        }    }    /**     * Checks and updates status for a node that failed to acquire.     * Returns true if thread should block. This is the main signal     * control in all acquire loops.  Requires that pred == node.prev     *     * @param pred node's predecessor holding status     * @param node the node     * @return {@code true} if thread should block     */    private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {        int s = pred.waitStatus;        if (s < 0)            /*             * This node has already set status asking a release             * to signal it, so it can safely park             */            return true;        if (s > 0)            /*             * Predecessor was cancelled. Move up to its predecessor             * and indicate retry.             */            node.prev = pred.prev;        else            /*             * Indicate that we need a signal, but don't park yet. Caller             * will need to retry to make sure it cannot acquire before             * parking.             */            compareAndSetWaitStatus(pred, 0, Node.SIGNAL);        return false;    }    /**     * Convenience method to interrupt current thread.     */    private static void selfInterrupt() {        Thread.currentThread().interrupt();    }    /**     * Convenience method to park and then check if interrupted     *     * @return {@code true} if interrupted     */    private final boolean parkAndCheckInterrupt() {        LockSupport.park(this);        return Thread.interrupted();    }    /*     * Various flavors of acquire, varying in exclusive/shared and     * control modes.  Each is mostly the same, but annoyingly     * different.  Only a little bit of factoring is possible due to     * interactions of exception mechanics (including ensuring that we     * cancel if tryAcquire throws exception) and other control, at     * least not without hurting performance too much.     */    /**     * Acquires in exclusive uninterruptible mode for thread already in     * queue. Used by condition wait methods as well as acquire.     *     * @param node the node     * @param arg the acquire argument     * @return {@code true} if interrupted while waiting     */    final boolean acquireQueued(final Node node, long arg) {        try {            boolean interrupted = false;            for (;;) {                final Node p = node.predecessor();                if (p == head && tryAcquire(arg)) {                    setHead(node);                    p.next = null; // help GC                    return interrupted;                }                if (shouldParkAfterFailedAcquire(p, node) &&                    parkAndCheckInterrupt())                    interrupted = true;            }        } catch (RuntimeException ex) {            cancelAcquire(node);            throw ex;        }    }    /**     * Acquires in exclusive interruptible mode.     * @param arg the acquire argument     */    private void doAcquireInterruptibly(long arg)        throws InterruptedException {        final Node node = addWaiter(Node.EXCLUSIVE);        try {            for (;;) {                final Node p = node.predecessor();                if (p == head && tryAcquire(arg)) {                    setHead(node);                    p.next = null; // help GC                    return;                }                if (shouldParkAfterFailedAcquire(p, node) &&                    parkAndCheckInterrupt())                    break;            }        } catch (RuntimeException ex) {            cancelAcquire(node);            throw ex;        }        // Arrive here only if interrupted        cancelAcquire(node);        throw new InterruptedException();    }    /**     * Acquires in exclusive timed mode.     *     * @param arg the acquire argument     * @param nanosTimeout max wait time     * @return {@code true} if acquired     */    private boolean doAcquireNanos(long arg, long nanosTimeout)        throws InterruptedException {        long lastTime = System.nanoTime();        final Node node = addWaiter(Node.EXCLUSIVE);        try {            for (;;) {                final Node p = node.predecessor();                if (p == head && tryAcquire(arg)) {                    setHead(node);                    p.next = null; // help GC                    return true;                }                if (nanosTimeout <= 0) {                    cancelAcquire(node);                    return false;                }                if (nanosTimeout > spinForTimeoutThreshold &&                    shouldParkAfterFailedAcquire(p, node))                    LockSupport.parkNanos(this, nanosTimeout);                long now = System.nanoTime();                nanosTimeout -= now - lastTime;                lastTime = now;                if (Thread.interrupted())                    break;            }        } catch (RuntimeException ex) {            cancelAcquire(node);            throw ex;        }        // Arrive here only if interrupted        cancelAcquire(node);        throw new InterruptedException();    }    /**     * Acquires in shared uninterruptible mode.     * @param arg the acquire argument     */    private void doAcquireShared(long arg) {        final Node node = addWaiter(Node.SHARED);        try {            boolean interrupted = false;            for (;;) {                final Node p = node.predecessor();                if (p == head) {                    long r = tryAcquireShared(arg);                    if (r >= 0) {                        setHeadAndPropagate(node, r);                        p.next = null; // help GC                        if (interrupted)                            selfInterrupt();                        return;                    }                }                if (shouldParkAfterFailedAcquire(p, node) &&                    parkAndCheckInterrupt())                    interrupted = true;            }        } catch (RuntimeException ex) {            cancelAcquire(node);            throw ex;        }    }    /**     * Acquires in shared interruptible mode.     * @param arg the acquire argument     */    private void doAcquireSharedInterruptibly(long arg)        throws InterruptedException {        final Node node = addWaiter(Node.SHARED);        try {            for (;;) {                final Node p = node.predecessor();                if (p == head) {                    long r = tryAcquireShared(arg);                    if (r >= 0) {                        setHeadAndPropagate(node, r);                        p.next = null; // help GC                        return;                    }                }                if (shouldParkAfterFailedAcquire(p, node) &&                    parkAndCheckInterrupt())                    break;            }        } catch (RuntimeException ex) {            cancelAcquire(node);            throw ex;        }        // Arrive here only if interrupted        cancelAcquire(node);        throw new InterruptedException();    }    /**     * Acquires in shared timed mode.     *     * @param arg the acquire argument     * @param nanosTimeout max wait time     * @return {@code true} if acquired     */    private boolean doAcquireSharedNanos(long arg, long nanosTimeout)        throws InterruptedException {        long lastTime = System.nanoTime();        final Node node = addWaiter(Node.SHARED);        try {            for (;;) {                final Node p = node.predecessor();                if (p == head) {                    long r = tryAcquireShared(arg);                    if (r >= 0) {                        setHeadAndPropagate(node, r);                        p.next = null; // help GC                        return true;                    }                }                if (nanosTimeout <= 0) {                    cancelAcquire(node);                    return false;                }                if (nanosTimeout > spinForTimeoutThreshold &&                    shouldParkAfterFailedAcquire(p, node))                    LockSupport.parkNanos(this, nanosTimeout);                long now = System.nanoTime();                nanosTimeout -= now - lastTime;                lastTime = now;

⌨️ 快捷键说明

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