AbstractQueuedSynchronizer(AQS)

AQS概念

java.util.concurrent包中的大多数同步器实现都是围绕着共同的继承行为,如:等待队列、条件队列、独占获取、共享获取等,而这些行为的抽象就是基于AbstractQueuedSynchronizer(简称AQS)实现的,AQS是一个抽象的同步框架,可以用来实现一个依赖状态的同步器。

AQS特性
  • 阻塞等待队列

  • 共享/独占

  • 公平/非公平

  • 可重入

  • 允许中断

AQS内部维护属性

volatile int state,State三种访问方式:

  • getState()

  • setState()

  • compareAndSetState()

AQS定义两种队列
  • 同步等待队列:主要用于维护获取锁失败时入队的线程

  • 条件等待队列:调用await()的时候会释放锁,然后线程会加入到条件队列,调用signal()唤醒的时候会把条件队列中的线程节点移动到同步队列中,等待再次获取锁。

AQS定义队列中节点的五种状态
  • 值为0,初始化状态,表示当前节点在sync队列中,等待着获取锁。

  • CANCELLED,值为1,表示当前的线程被取消。

  • SIGNAL,值为-1,表示当前节点的后续节点包含的线程需要运行,也就是unpark。

  • CONDITION,值为-2,表示当前节点在等待condition,也就是在condition队列中。

  • PROPAGATE,值为-3,表示当前场景下后续的acquireShared能够得以执行。

自定义同步器

不同的自定义同步器竞争共享资源的方式也不同。自定义同步器在实现时只需要实现共享资源state的获取与释放方式即可,至于具体线程等待队列的维护(如获取资源失败入队/唤醒出队等),AQS已经在顶层实现好了。自定义同步器实现时主要实现以下几种方法:

  • isHeldExclusively():该线程是否正在独占资源。只有用到condition才需要去实现它。

  • tryAcquire(int):独占方式。尝试获取资源,成功则返回true,失败则返回false。

  • tryRelease(int):独占方式。尝试释放资源,成功则返回true,失败则返回false。

  • tryAcquireShared(int):共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。

  • tryReleaseShared(int):共享方式。尝试释放资源,如果释放后允许唤醒后续等待结点返回true,否则返回false。

同步等待队列

AQS中的同步等待队列也称为CLH队列(Craig、Landin、Hagersten三人发明的),是一种基于双向链表数据结构的队列,AQS 依赖CLH同步队列来完成同步状态的管理:

  • 当前线程如果获取同步状态失败时,AQS则会将当前线程已经等待状态等信息构造成一个节点(Node)并将其加入到CLH同步队列,同时会阻塞当前线程。

  • 当同步状态释放时,会把首节点唤醒(公平锁),使其再次尝试获取同步状态。

  • 通过signal或signalAll将条件队列中的节点转移到同步队列。(由条件队列转化为同步队列)

条件等待队列

AQS中条件队列是使用单向列表保存的,用nextWaiter来连接。

  • 调用await方法阻塞线程;

  • 当前线程存在于同步队列的头结点,调用await方法进行阻塞(从同步队列转化到条件队列)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值