想了很久java.util.concurrent.AQS中的锁切换问题

问题描述

    final boolean acquireQueued(final Node node,int arg) {
        boolean Failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    Failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p,node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (Failed)
                cancelAcquire(node);
        }
    }
    /**
     * Releases in exclusive mode.  Implemented by unblocking one or
     * more threads if {@link #tryRelease} returns true.
     * This method can be used to implement method {@link Lock#unlock}.
     *
     * @param arg the release argument.  This value is conveyed to
     *        {@link #tryRelease} but is otherwise uninterpreted and
     *        can represent anything you like.
     * @return the value returned from {@link #tryRelease}
     */
    public final boolean release(int arg) {
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }
    private void unparkSuccessor(Node node) {
        /*
         * If status is negative (i.e.,possibly needing signal) try
         * to clear in anticipation of signalling.  It is OK if this
         * fails or if status is changed by waiting thread.
         */
        int ws = node.waitStatus;
        if (ws < 0)
            compareAndSetWaitStatus(node,ws,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);
    }

线程A调用tryRelease方法成功释放锁并唤醒后继线程。如果后继线程此时没有park,但是tryAcquire成功获取了锁,那么线程A会unpark一个正常执行的线程。这样,后续调用就会有不确定因素。 Doug Lea 的考虑是什么?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)