AbstractQueuedSynchronizer(AQS)

来源:互联网 发布:股票实时数据 大智慧 编辑:程序博客网 时间:2024/06/05 07:30
最后总结:
AQS主要管理共用某资源的thread,这些thread用Node包装,然后用AQS的Node head、tail来管理,
这些thread何时可以获取(tryacquire )锁,都由AQS的管理机制来决定。
主要参考资料:源码以及http://www.iigrowing.cn/java_duo_xian_cheng_zhong_gong_ping_suo_1.html 

Wait queue node class:
等待队列(wait queue)是一个“CLH”锁队列的变形,CLH通常被用于自旋锁(spinlock)。
这个类中不是用阻塞同步器(blocking synchronizer),而是用
同一种基本策略:即使用此node的前node(node.pre)所包含的关于一个thread
的控制信息。
每个node的“status”域跟踪指示一个thread是否应该进入block状态。当node.pre被
释放,则node会接收到通知信号。另外,queue中的每个node作为一个“具体通知
式”(specific-notification-style)监控器,控制它所持有的等待线程(waiting thread)。
但是status域并不会控制线程是否被赋予锁。
一个在queue首位的thread可能(may)会试着去获取锁,但是位于queue首这个条件
并不是保证其能成功获得锁,而只会让有成为了锁的竞争者之一。所以刚释放的竞争者
thread需要重新等待(rewait)。

像一个CLH queue插入一个node,只需要在queue的tail进行一次原子操作,所以在
unqueued和queued之间只存在一个简单的原子操作的界限。类似的,dequeue只涉及
update一下head。但是,dequeue一个node,需要一些额外工作来确定哪个新的node是
此dequeued的node的继任者,这额外工作还包括处理由于timeout和interrupt引起的任务取消。
prev链接主要被用来处理cancellation,如果一个node已经取消(结束?)(cancelled),
它的继任者会(通常)重新链接到一个未cancelled的前任(predecessor)。

Node里面有个waitStatus参数,可取得值为:

*   SIGNAL(-1):     The successor of this node is (or will soon be)
*               blocked (via park), so the current node must
*               unpark its successor when it releases or
*               cancels. To avoid races, acquire methods must
*               first indicate they need a signal,
*               then retry the atomic acquire, and then,
*               on failure, block.
*   CANCELLED(1):  This node is cancelled due to timeout or interrupt.
*               Nodes never leave this state. In particular,
*               a thread with cancelled node never again blocks.
*   CONDITION(-2):  This node is currently on a condition queue.
*               It will not be used as a sync queue node
*               until transferred, at which time the status
*               will be set to 0. (Use of this value here has
*               nothing to do with the other uses of the
*               field, but simplifies mechanics.)
*   PROPAGATE(-3):  A releaseShared should be propagated to other
*               nodes. This is set (for head node only) in
*               doReleaseShared to ensure propagation
*               continues, even if other operations have
*               since intervened.
*   0:          None of the above

CANCELLED[1]  -- 当前线程已被取消
SIGNAL[-1]    -- “当前线程的后继线程需要被unpark(唤醒)”。一般发生情况是:当前线程的后继线程处于阻塞状态,而当前线程被release或cancel掉,因此需要唤醒当前线程的后继线程。
CONDITION[-2] -- 当前线程(处在Condition休眠状态)在等待Condition唤醒
PROPAGATE[-3] -- (共享锁)其它线程获取到“共享锁”
[0]           -- 当前线程不属于上面的任何一种状态。
主要方法:

/**
* Wakes up node's successor, if one exists.
*
*@param node the node
*/
private void unparkSuccessor(Nodenode) {
    /*
     * 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(Nodet = tail;t != null && t != node;t = t.prev)
            if(t.waitStatus<= 0)
                s = t;
    }
    if(s!= null)
        LockSupport.unpark(s.thread);
}
找到waitStatus<=0的最接近入参node的node1,如果node1不为null,将此node1 unpark(即继续执行此node1)

/** Marker to indicate a node is waiting in shared mode */
static final NodeSHARED = new Node();
/** Marker to indicate a node is waiting in exclusive mode */
static final NodeEXCLUSIVE = null;

Node nextWaiter;

/**
* Returns true if node is waiting in shared mode.
*/
final boolean isShared() {
    returnnextWaiter ==SHARED;
}
// nextWaiter是“区别当前CLH队列,是 ‘独占锁’队列 还是 ‘共享锁’队列 的标记”
    // 若nextWaiter=SHARED,则CLH队列是“独占锁”队列;
    // 若nextWaiter=EXCLUSIVE,(即nextWaiter=null),则CLH队列是“共享锁”队列。
    Node nextWaiter;

    // “共享锁”则返回true,“独占锁”则返回false。
    final boolean isShared() {
        return nextWaiter == SHARED;
    }


原创粉丝点击