AQS数据结构及源码解析

AQS 数据结构

AQS数据结构图

数据结构分为两部分。第一行的同步队列,用于排队所有的的等待线程一次获取锁。第二、三行是条件队列,每一行对应当前lock锁的一个条件Condition。
还有一部分没有画出来,是条件队列中节点在signal()方法中会enq入队到第一行的同步队列中去获取锁,这时条件队列的node节点中的prev、next会指向同步队列的节点上。

同步队列(sync queue)

基于双向链表的同步队列,头尾指针head、tail。同步队列的修改是线程安全的,因为会有多线程的竞争。
每一个node在同步队列中都代表一个正在等待获取锁的线程,也是首次获取锁失败后才进入同步队列进行等待的线程。第一个node代表当前获得锁的线程,由head指向首个节点。

重要属性解析

  • prev指针作用:prev == head 成功,是去争夺锁的前提条件。只有当一个node的prev已经是head时,该node才有可能获得锁,即就是锁的获取过程遵从sync queue的顺序排列过程。
  • next指针作用:当prev在释放锁的时候,通过next指针找到下一个需要获得锁的节点及其对于线程。
  • waitStatus:这个属性比较重要,0是默认值,和PROPATION一样是指要向后传递,但PROPATION只设置在首节点(即head);CONDITION指该node为一个等待信号的节点,常用在条件队列中;CANCELED是指当前node被取消了,可能出现在同步队列和等待队列中(被取消的原因可能由释放锁失败,此作用在await()#fullRelease()方法中,后续会讨论)。

node有五个最重要的属性

  • prev:前一个节点指针
  • next:后一个节点指针
  • waitStatus:当前节点的等待状态,有0(默认)、PROPAGATION、SIGNAL、CONDITION、CANCELED 五种
  • thread:当前排队的线程
  • nextWaiter:mode,有三种值Node.SHARED,Node.EXCLUSIVE,条件队列中下一个node的指针

node两种节点类型

  • EXECLUDE:排它锁
  • SHARED:共享锁

条件队列(condition queue)

基于单向链表的非同步队列,头尾指针为firstWaiter、lastWaiter。条件队列为非同步队列,修改条件队列的线程必须获得当前锁lock,故不存在多线程竞争。

node有五个重要属性

  • nextWaiter:条件队列中下一个节点指针
  • thread:当前排队的线程
  • prev:保留,后面指向同步队列的某节点上
  • next:保留,后面指向同步队列的某节点上
  • waitStatus:条件队列只有 CONDITION 一种值

节点类型

  • 此时waitStatus就是指针,没有特殊类型

条件队列节点enq到同步队列

条件队列的原理就是,先调用await() 让当前线程进入到某个条件的条件队列中睡眠等待,直到signal信号唤醒后,争夺锁成功返回继续执行await()后面的代码,以此达到最终一种 等待-唤醒 模式实现线程间通信协作。

而条件队列节点被唤醒后若想重新获取到锁,一定要先node进入到sync queue中排队获取排它锁,将来才有可能等到锁。因为此时可能会有线程已经获得锁,同时有很多线程已经在等待获取锁了,故只要一样加入等待锁的同步队列即可。

AQS都有哪些特点:

这里会先汇总AQS的一些特点以及都包含了哪些类型的锁,有一个整体的认知。

  1. 共享锁、排它锁
  2. 公平锁、非公平锁
  3. 阻塞式锁、非阻塞式锁、超时锁
  4. 可中断锁、不可中断锁
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值