美文网首页
AbstractQueuedSynchronizer (AQS)

AbstractQueuedSynchronizer (AQS)

作者: sha4yu0119 | 来源:发表于2020-05-08 22:56 被阅读0次

    双队列

    在AQS中,存在两个队列

    AQS两队列
    • 等待队列:用于挂起当前线程,等待某个条件满足后唤醒或是被中断。
    • 同步队列:多线程竞争锁时,如果存在竞态,则放入同步队列,等待唤醒重新竞争。

    等待队列维护在 AQS.ConditionObject 中,而同步队列维护在AQS中。
    等待队列中的元素被唤醒后,会被移至同步队列,待重新竞争获得锁后,线程才能继续执行。示意代码如下

    ReentrantLock lock = new ReentrantLock();
    Conditon condition = lock.newCondition();
    // thread 1
    void run() {
        try {
          lock.lock();
          condition.await(); // 执行后,当前线程会被加入等待队列,等待signal信号或是被中断
        } catch (Exception e) {
        } finally {
          lock.unlock();
        }
    }
    
    // thread 2
    void run() {
        try {
          lock.lock();
          condition.signal();  // 执行后,等待队列中的第一个线程会被唤醒,并从等待队列中移除,添加至同步队列
        } catch (Exception e) {
        } finally {
          lock.unlock();
        }
    }
    
    

    调用路线是 Condition::signal -> Condition::doSignal -> AQS::transferForSignal 其中调用了 AQS::enq 将元素推至同步队列,而Condition::doSignal 中,唤醒的线程会从等待队列中移除。

    Node

    AQS的内部类 Node是核心数据结构。等待队列和同步队列都是由其实现,可以简化为

    class Node {
      Node nextWaiter; // 值有两种可能 SHARED, EXCLUSIVE
      int waitStatus;  // CANCELLED  SIGNAL  CONDITION  PROPAGATE
      Node prev; // 双向链表,指向前一个元素
      Node next; // 双向链表,指向下一个元素
    }
    

    state

    State在AQS极具扩展性,在不同的实现中,state作为一个int代表了多种状态

    • 在 CountDownLatch 中,state 表示剩余的计数个数。为0时,结束。
    • 在 Semaphore 中,state 表示剩余许可的个数。
    • 在 ReentrantLock 中,state 表示锁的占用状态,0为可抢占,大于0则不可抢占,且表示了重入的次数。
    • 在 ReentrantReadWriteLock 中,state 低16位表示写锁,高16位表示读锁。同步队列中存放着竞争读锁的线程。

    开放的接口

    我以为,AQS的扩展性在于其同步队列和State。一个用于存储资源竞争者,一个用于标识资源的可用状态。目前理解还很肤浅,如有错误,望不吝赐教。

    相关文章

      网友评论

          本文标题:AbstractQueuedSynchronizer (AQS)

          本文链接:https://www.haomeiwen.com/subject/lllcnhtx.html