AQS(AbstractQueuedSynchronizer)是Java并发包中的一个核心基础类,用于构建锁和同步器。它的主要原理是通过一个整型的状态变量(state)来表示同步状态,并使用一个FIFO(先进先出)的等待队列来管理获取锁失败的线程。
以下是AQS的几个关键点:
- 状态变量(state) :
- AQS使用一个
volatile
的整型变量state
来表示同步状态。state
的默认值为0,表示资源可用;当线程获取锁成功时,state
加1;当线程释放锁时,state
减1。这种机制确保了加锁和释放锁的原子性。
- 等待队列(等待队列) :
- AQS内部维护一个FIFO的双向队列,用于存放那些尝试获取锁但失败的线程。队列中的每个节点(Node)包含线程的信息以及等待状态。当线程获取锁失败时,它会被封装成一个节点并加入到队列的尾部,同时该线程会被阻塞。
- 锁的获取和释放 :
-
当线程尝试获取锁时,它会检查
state
的值。如果state
为0,表示锁可用,线程会通过CAS(Compare-and-Swap)操作将state
加1,从而成功获取锁。如果state
不为0,表示锁已被占用,线程会被加入到等待队列中。 -
当线程释放锁时,它会执行
state
减1的操作,并通过CAS操作确保只有持有锁的线程才能释放锁。释放锁后,AQS会从等待队列的头部唤醒一个线程,使其尝试获取锁。
- 公平性和非公平性 :
- AQS支持公平锁和非公平锁。在公平锁中,锁的释放会按照等待队列的顺序唤醒线程;在非公平锁中,新来的线程有可能在等待队列中的线程之前获取到锁。
- 扩展性 :
- AQS是许多Java并发工具类的基础,如
ReentrantLock
、ReentrantReadWriteLock
、Semaphore
等。这些类通过继承AQS并重写相关方法来实现自己的同步逻辑。
总结起来,AQS通过一个状态变量和等待队列来实现线程的同步和锁的管理,确保在多线程环境下资源的互斥访问。这种设计不仅简单高效,而且具有良好的扩展性,使得开发者可以基于AQS构建出各种复杂的同步器。