AbstractQueuedSynchronizer总结

目录

1、简介

2、原理

2.1、数据结构

2.2、节点对象

3、使用

3.1、状态变迁

3.2、子类需实现的API

3.3、同步器中的模板方法

4、LockSupport


1、简介

AbstractQueuedSynchronizer (抽象队列同步器,以下简称 AQS)出现在 JDK 1.5 中,由大师 Doug Lea 所创作。AQS 是很多同步器的基础框架,比如 ReentrantLock、CountDownLatch 和 Semaphore 等都是基于 AQS 实现的。除此之外,我们还可以基于 AQS,定制出我们所需要的同步器。

2、原理

2.1、数据结构

在 AQS 内部,通过维护一个FIFO 队列来管理多线程的排队工作。在公平竞争的情况下,无法获取同步状态的线程将会被封装成一个节点,置于队列尾部。入队的线程将会通过自旋的方式获取同步状态,若在有限次的尝试后,仍未获取成功,线程则会被阻塞住。大致示意图如下:

当头结点释放同步状态后,且后继节点对应的线程被阻塞,此时头结点线程将会去唤醒后继节点线程。后继节点线程恢复运行并获取同步状态后,会将旧的头结点从队列中移除,并将自己设为头结点。大致示意图如下:

2.2、节点对象

Node {
    int waitStatus;
    Node prev;
    Node next;
    Node nextWaiter;
    Thread thread;
}
属性名称描述
int waitStatus表示节点的状态。其中包含的状态有:

1、CANCELLED,值为1,表示当前的线程被取消;

2、SIGNAL,值为-1,表示当前节点的后继节点包含的线程需要运行,也就是unpark;

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

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

5、值为0,表示当前节点在sync队列中,等待着获取锁。

Node prev前驱节点,比如当前节点被取消,那就需要前驱节点和后继节点来完成连接。
Node next后继节点。
Node nextWaiter存储condition队列中的后继节点。
Thread thread入队列时的当前线程。

3、使用

3.1、状态变迁

使用的方法是继承,子类通过继承同步器并需要实现它的方法来管理其状态,管理的方式就是通过类似acquire和release的方式来操纵状态。然而多线程环境中对状态的操纵必须确保原子性,因此子类对于状态的把握,需要使用这个同步器提供的以下三个方法对状态进行操作:

int getState()	 获取同步状态
void setState()	 设置同步状态
boolean compareAndSetState(int expect, int update)	 通过CAS设置同步状态

子类推荐被定义为自定义同步装置的内部类,同步器自身没有实现任何同步接口,它仅仅是定义了若干acquire之类的方法来供使用。该同步器即可以作为排他模式也可以作为共享模式,当它被定义为一个排他模式时,其他线程对其的获取就被阻止,而共享模式对于多个线程获取都可以成功。

3.2、子类需实现的API

方法名称描述
protected boolean tryAcquire(int arg)排它的获取这个状态。这个方法的实现需要查询当前状态是否允许获取,然后再进行获取(使用compareAndSetState来做)状态。
protected boolean tryRelease(int arg) 释放状态。
protected int tryAcquireShared(int arg)共享的模式下获取状态。
protected boolean tryReleaseShared(int arg)共享的模式下释放状态。
protected boolean isHeldExclusively()在排它模式下,状态是否被占用。

实现这些方法必须是非阻塞而且是线程安全的,推荐使用该同步器的父java.util.concurrent.locks.AbstractOwnableSynchronizer来设置当前的线程。

3.3、同步器中的模板方法

方法说明
void acquire(int arg)独占式获取同步状态,该方法将会调用 tryAcquire 尝试获取同步状态。获取成功则返回,获取失败,线程进入同步队列等待。
void acquireInterruptibly(int arg)响应中断版的 acquire
boolean tryAcquireNanos(int arg,long nanos)超时+响应中断版的 acquire
void acquireShared(int arg)共享式获取同步状态,同一时刻可能会有多个线程获得同步状态。比如读写锁的读锁就是就是调用这个方法获取同步状态的。
void acquireSharedInterruptibly(int arg)响应中断版的 acquireShared
boolean tryAcquireSharedNanos(int arg,long nanos)超时+响应中断版的 acquireShared
boolean release(int arg)独占式释放同步状态
boolean releaseShared(int arg)共享式释放同步状态

4、LockSupport

点击跳转

https://segmentfault.com/a/1190000014721183

http://ifeve.com/introduce-abstractqueuedsynchronizer/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值