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; // 阻塞队列的尾,在初始化之后,它只通过casTail修改

private volatile int state; // 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; // initially attached via casTail
volatile Node next; // visibly nonnull when signallable
Thread waiter; // visibly nonnull when enqueued
volatile int status; // written by owner, atomic bit ops by others

// methods for atomic operations
final boolean casPrev(Node c, Node v) { // for cleanQueue
return U.weakCompareAndSetReference(this, PREV, c, v);
}
final boolean casNext(Node c, Node v) { // for cleanQueue
return U.weakCompareAndSetReference(this, NEXT, c, v);
}
final int getAndUnsetStatus(int v) { // for signalling
return U.getAndBitwiseAndInt(this, STATUS, ~v);
}
final void setPrevRelaxed(Node p) { // for off-queue assignment
U.putReference(this, PREV, p);
}
final void setStatusRelaxed(int s) { // for off-queue assignment
U.putInt(this, STATUS, s);
}
final void clearStatus() { // for reducing unneeded signals
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");
}