AbstractQueuedSynchronizer(一)

115 阅读2分钟
AQS提供了一套通用的机制来管理同步状态、阻塞/唤醒线程、管理等待队列

资源是可以被同时访问还是在同一时间只能被一个线程访问(共享/独占)

访问资源的线程如何进行并发管理(等待队列)

如果线程等不及资源了,如何从等待队列退出(超时/中断)

常见同步器对资源以及对资源访问这个问题的定义

ReentrantLock

资源表示独占锁,state为0表示锁可用,为1表示被占用,为n表示可重入以及次数

CountDownLatch

资源表示倒数计数器,state为0表示所有的线程都可以访问资源,为n表示所有线程都需要阻塞

Semaphore

资源表示信号量或令牌,state<=0表示所有线程都需要阻塞,>0表示有令牌可用,线程每获取一个令牌state减1,线程每释放一个令牌state加1

ReentrantReadWriteLock

资源表示共享的读锁和独占的写锁,state逻辑上被分为两个16位的unsigned short,分别记录读锁被多少线程使用和写锁被重入的次数

AQS通过暴露以下API来解决如何定义资源是否可以被访问的问题

一、同步状态的管理

AQS使用单个int来保存同步状态,并通过getState、setState、compareAndSetState来读取和更新这个状态。

二、数据结构

AQS内部维护着一个FIFO的队列,该队列用来实现线程的并发访问控制。队列中的元素是一个Node类型的节点。

1、waitStatus:表示节点的状态

          CANCELLED:值为1,表示当前节点被取消

          SIGNAL:值为-1,表示当前节点的后继节点将要或已经被阻塞

          CONDITION:值为-2,表示当前节点在等待condition,在condition队列中

          PROPAGATE:值为-3,表示releaseShared需要被传播给后续节点

          INITAL:值为0,默认状态,新节点处于该状态

2、prev:前置节点

3、next:后置节点

4、nextWaiter:存储condition队列中的后置节点

5、thread:当前线程

当线程请求资源时,如果请求不到,会将线程包装成节点,将其插入队列的尾部

1、初始状态,队列head、tail都指向空

2、首个线程入队,先创建一个空的头节点,然后以自旋的方式不断尝试插入一个包含当前线程的新节点




           欢迎关注我的微信公众号,分享leetcode解题心得和Java后端的相关知识