AbstractQueuedSynchronizer解析

AbstractQueuedSynchronizer ,本文简称aqs,是java锁机制的基类

1  aqs的父类

  

   aqs 的直接父类  AbstractOwnableSynchronizer  aos 中的 私有变量 exclusiveOwnerThread 表示持有锁的线程

2  aqs中的队列

     aqs, 基于fifo的等待队列,可支持 阻塞锁、信号量(semaphores) 。

     包括两种  sync队列           由双向链表实现,组成Node有共享、排他两种模式,共享模式允许多个线程持有锁,排他模式只允许单个线程持有锁

                      monitor队列      由单项链表实现,组成Node只有排他模式

     两种队列都是由Node节点组成的,每个node节点持有对应的线程

Node节点结构 sync队列 monitor队列

          等待状态  waitStatus

          前驱节点 prev --

         后继节点 next --

      对应线程    thread

        下个等待节点    nextWaiter 用来表示共享、排他两种模式 用来表示下个节点

等待状态(waitStatus)有:  

      1  CANCELLED  值1   代表该节点对应的线程已被取消

         2  SIGNAL          值-1  代表该节点的后继节点的线程需要唤醒(unparking)

         3  CONDITION   值-2  代表该节点对应线程处于 等待池(wait on condition)

         4  PROPAGATE 值-3  代表 下个共享节点 无条件传播

        5  0                     值0  代表当前节点

3   sync队列

        结构 :

           头节点 Node head

           尾节点 Node tail

       队列状态 int state           信号量Semaphore 通过该字段的值控制持有锁的线程数

                                                   CountdownLatch 通过该字段初始化coutdown线程数 

                                                   ReentrantLock   通过该字段记录锁重入次数,判断锁的获得与释放

                                         对应的方法有 三个   int getState()                    获取state (持有锁的线程数、)

          setState(int newState)             初始化state(允许的许可量)

  boolean compareAndSetState(int expect, int update)  动态乐观更新(重入次数,剩余许可量等)

         

        方法:  

(1)入队    Node enq(final Node node) 

                                  入队方法中包括了 head tail 的初始化、node加入队尾两部分,通过cas方法 (乐观锁)的方式实现,如果初始化、node入队失败,代表其他线程同时初始化或入队成功,需要重试(放在for循环中),对应源码:

                                  

  (2) 入队waiter  Node addWaiter(Node mode)

                                     入队waiter时,指定当前线程 是共享还是排他模式入队。

                                     下图try the fast ,比直接 入队快在没有for循环。

                    (3)设置头结点

                                     node设置为头结点,node对应线程出sync队列,null字段方便gc

                (4)    唤醒后继节点  unparkSuccessor(Node node)  

                                         1 设置当前节点为 waitStatus 为0, 

                                         2  唤醒后继节点 或最近后继节点

                (5)    释放(共享模式)  

对 SIGNAL 节点,waitStatus置位0,唤醒后继或最近后继节点;

对0节点,waitStatus置为 PROPAGATE 

    (6)设置头结点并 释放

    (7) 取消获取     cancelAcquire(Node node)

                                     1 找到node 最近 非取消的 前置节点 pred

                   2  设置node    waitStatus  为  CANCELLED  

                                     3  如果node为队尾,node出队,pred设置为队尾

                                             node不为队尾,pred不是队头, 设置pred waitStatus为SIGNAL , 

                                                                              node的后置节点waitStatus<=0时, pred指向 node的后置节点

                                                                       pred是队头,唤醒node

                   (8) 获取失败后等待   shouldParkAfterFailedAcquire(Node pred, Node node)

                   (9)获取 boolean acquireQueued(final Node node, int arg)

                               node获取的锁,如果前置节点是head,去获取

        

                     自中断   

    子类获取、释放锁时修改state(int)

     支持 排他 共享两种模式,排他即独占,共享可限制最大数量

     

     

     

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值