AQS의 원인을 파악하기 위해 간단한

개념

AQS는 AbstractQueuedSynchronizer의를 의미합니다.

AQS 자물쇠 각종 동기 다양한 컴포넌트를 구현하기 위해 사용 계약 단위 및 구성 요소이다. 이는 동시 큐의 핵심 성분을 기다리는 쓰레드를 잠금 상태 변수를 포함한다.

ReentrantLock와, 세마포어, CountDownLatch를, FutrueTask, 이러한 기반이 AQS 내장.

AQS / 쓰기 및 기반 CAS 휘발성 변수 (즉,의 compareAndSet () 메소드) 판독 달성하는 것이다.

휘발성 또한 명령 순서 변경을 금지 할 수 동시성의 가시성을 보장합니다. CAS는 공유 데이터에 대한 동시 액세스를 관리하는 데 사용됩니다.

AQS와 관계 ReentrantLock와

ReentrantLock와에서 상태는 잠금 상태를 나타낸다. 초기 상태에서, 상기 상태 값은 0이다.

또한, AQS가 잠겨 스레드 현재 레코드, 초기화 상태에 대한 중요한 변수가 내부에,이 변수는 널이다.

스레드가 잠금 잠금 ReentrantLock와 () 메소드를 호출 시도를 실행하기 위해, 로크 프로세스는 0 내지 1 CAS 직접 작동 상태 값을 사용하는 것이다.
당신이 잠금 전에 한 명을 추가하지 않으면, 다음 상태의 값은 확실히 0, 다음 스레드가 성공적으로 잠글 수 있습니다.
고정 나사 1이 성공하면 현재의 thread가 자신을 잠금 설정할 수 있습니다.

주요 흐름

중요 변수

  • 상태
    상태 변수.
/**
 * The synchronization state.
 */
private volatile int state;

노드 노드 큐 대기

"CLH"(크레이그, Landin 및 Hagersten) 잠금 큐.

CLH 로크 큐 일반적 동시 상황을 처리하기 위해 사용되고, 그것은 양방향 동기화 상태 큐 (FIFO)를 통해 달성된다. 각 스레드 동기화 큐 노드 노드로 캡슐화된다.

각 노드 노드 큐는 현재 스레드 동기화, 대기 상태, 전임자와 후임자 노드 등의 상태를 저장합니다.

static final class Node {
        //共享模式
        /** Marker to indicate a node is waiting in shared mode */
        static final Node SHARED = new Node();
        //独占模式
        /** Marker to indicate a node is waiting in exclusive mode */
        static final Node EXCLUSIVE = null;

        // 线程的等待状态 表示线程已经被取消
        static final int CANCELLED =  1;
        // 线程的等待状态 表示后继线程需要被唤醒
        static final int SIGNAL    = -1;
        // 线程的等待状态 表示线程在Condtion上
        static final int CONDITION = -2;
        // 表示下一个acquireShared需要无条件的传播
        static final int PROPAGATE = -3;

        /**
         *   等待状态有以下几种:
         *   
         *   SIGNAL:     当前节点的后继节点处于等待状态时,如果当前节点的同步状态被释放或者取消,
         *               必须唤起它的后继节点
         *         
         *   CANCELLED:  一个节点由于超时或者中断需要在CLH队列中取消等待状态,被取消的节点不会再次等待
         *               
         *   CONDITION:  当前节点在等待队列中,只有当节点的状态设为0的时候该节点才会被转移到同步队列
         *               
         *   PROPAGATE:  下一次的共享模式同步状态的获取将会无条件的传播
 
         *   waitStatus的初始值时0,使用CAS来修改节点的状态
         */
        volatile int waitStatus;

        /**
         * Link to predecessor node that current node/thread relies on
         * for checking waitStatus. Assigned during enqueuing, and nulled
         * out (for sake of GC) only upon dequeuing.  Also, upon
         * cancellation of a predecessor, we short-circuit while
         * finding a non-cancelled one, which will always exist
         * because the head node is never cancelled: A node becomes
         * head only as a result of successful acquire. A
         * cancelled thread never succeeds in acquiring, and a thread only
         * cancels itself, not any other node.
         */
        volatile Node prev;

        /**
         * Link to the successor node that the current node/thread
         * unparks upon release. Assigned during enqueuing, adjusted
         * when bypassing cancelled predecessors, and nulled out (for
         * sake of GC) when dequeued.  The enq operation does not
         * assign next field of a predecessor until after attachment,
         * so seeing a null next field does not necessarily mean that
         * node is at end of queue. However, if a next field appears
         * to be null, we can scan prev's from the tail to
         * double-check.  The next field of cancelled nodes is set to
         * point to the node itself instead of null, to make life
         * easier for isOnSyncQueue.
         */
        volatile Node next;

        /**
         * The thread that enqueued this node.  Initialized on
         * construction and nulled out after use.
         */
        volatile Thread thread;

        /**
         * 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
         * linked queue to hold nodes while they are waiting on
         * conditions. They are then transferred to the queue to
         * re-acquire. And because conditions can only be exclusive,
         * we save a field by using special value to indicate shared
         * mode.
         */
        Node nextWaiter;

        /**
         * Returns true if node is waiting in shared mode.
         */
        final boolean isShared() {
            return nextWaiter == SHARED;
        }

        /**
         * Returns previous node, or throws NullPointerException if null.
         * Use when predecessor cannot be null.  The null check could
         * be elided, but is present to help the VM.
         *
         * @return the predecessor of this node
         */
        final Node predecessor() throws NullPointerException {
            Node p = prev;
            if (p == null)
                throw new NullPointerException();
            else
                return p;
        }

        Node() {    // Used to establish initial head or SHARED marker
        }

        Node(Thread thread, Node mode) {     // Used by addWaiter
            this.nextWaiter = mode;
            this.thread = thread;
        }

        Node(Thread thread, int waitStatus) { // Used by Condition
            this.waitStatus = waitStatus;
            this.thread = thread;
        }
    }

얻다()

스레드 전용 모드로 상태를 가져옵니다.

서브 클래스 상속 AQS 후, 종종 취득을 사용 (), 릴리스 ().

취득은 () 상태, 유지 보수 상태를 얻을 수있다.

/**
 * Acquires in exclusive mode, ignoring interrupts.  Implemented
 * by invoking at least once {@link #tryAcquire},
 * returning on success.  Otherwise the thread is queued, possibly
 * repeatedly blocking and unblocking, invoking {@link
 * #tryAcquire} until success.  This method can be used
 * to implement method {@link Lock#lock}.
 *
 * @param arg the acquire argument.  This value is conveyed to
 *        {@link #tryAcquire} but is otherwise uninterpreted and
 *        can represent anything you like.
 */
public final void acquire(int arg) {
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
        selfInterrupt();
}

해제()

스레드 전용 모드에서 상태를 해제합니다.

/**
 * 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;
}

unparkSuccessor ()

노드의 후속 노드를 깨워.

    /**
     * Wakes up node's successor, if one exists.
     *
     * @param node the node
     */
    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);
    }

compareAndSetState ()

설정 상태 변수 CAS. 국가가 지정한 매개 변수가 예상 될 때, 다른에 지정된 값을 수정합니다.

/**
 * Atomically sets synchronization state to the given updated
 * value if the current state value equals the expected value.
 * This operation has memory semantics of a {@code volatile} read
 * and write.
 *
 * @param expect the expected value
 * @param update the new value
 * @return {@code true} if successful. False return indicates that the actual
 *         value was not equal to the expected value.
 */
protected final boolean compareAndSetState(int expect, int update) {
    // See below for intrinsics setup to support this
    return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}

ConditionObject가

ConditionObject가 다른 내부 클래스 구현 조건 인터페이스 및 AWAIT () 신호 () signalALL 달성 () 방법 등.
ConditionObject가 주로 동시 구현을위한 특정 조건을 충족하지 않는 스레드 대기 시간을 일시 중단 할 수 있습니다, 프로그래밍 통보하는 동기 대기를 제공한다. 어떤 조건이되면 웨이크 업 스레드를 충족 될 때까지.

참고 :

https://juejin.im/post/5c07e59cf265da617464a09c합니다 (AQS의 이해에 대한 특유의 이야기)

http://ifeve.com/introduce-abstractqueuedsynchronizer/

https://blog.csdn.net/qq_30572275/article/details/80297047

추천

출처www.cnblogs.com/expiator/p/12052125.html