AQS详解
[toc]
AQS - AbstractQueuedSynchronizer,抽象队列同步器,构建锁和其他同步组件的基础框架。提供了共享锁和排它锁。
AQS常见的实现类:
- ReentrantLock 阻塞式锁
- Semaphore 信号量
- CountDownLatch 倒计时锁
其中:ReentrantLock使用了排它锁,而Semaphore和CountDownLatch使用的是共享锁
AQS工作原理
在AQS中有个volatile变量state(保证可见性),0表示无锁,1表示有锁。
一个线程获取锁资源时,判断state是否为0,若是把0改为1(这里使用CAS操作保证原子性),表示持有锁,其他的线程由于抢不到锁进入阻塞队列(双向链表,有头指针和尾指针)。拿到锁的线程执行结束后,会把state改为0并唤醒队列的head元素
- AQS中使用CAS操作state保证原子性
- 既可以实现公平锁也可以实现非公平锁
- 新的线程与队列中的线程共同争抢资源,是非公平锁
- 新的线程必须先加入队列等待,只允许队列的head元素获得锁,是公平锁
AQS源码分析
AQS的成员变量如下:
1 2 3 4 5
| private transient volatile Node head;
private transient volatile Node tail;
private volatile int state;
|
Node节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| abstract static class Node { volatile Node prev; volatile Node next; Thread waiter; volatile int status;
final boolean casPrev(Node c, Node v) { return U.weakCompareAndSetReference(this, PREV, c, v); } final boolean casNext(Node c, Node v) { return U.weakCompareAndSetReference(this, NEXT, c, v); } final int getAndUnsetStatus(int v) { return U.getAndBitwiseAndInt(this, STATUS, ~v); } final void setPrevRelaxed(Node p) { U.putReference(this, PREV, p); } final void setStatusRelaxed(int s) { U.putInt(this, STATUS, s); } final void clearStatus() { U.putIntOpaque(this, STATUS, 0); }
private static final long STATUS = U.objectFieldOffset(Node.class, "status"); private static final long NEXT = U.objectFieldOffset(Node.class, "next"); private static final long PREV = U.objectFieldOffset(Node.class, "prev"); }
|