点击去看看个人需求(比如低价【5折】耐克、阿迪达斯等轻奢品)
一. AQS是什么
队列同步器AbstractQueuedSynchronizer(简称为AQS),是用来构建锁或者其他同步组件的基础框架,通过内置的FIFO(先来先服务)队列来完成资源获取线程的排队工作。AQS是实现锁的关键,简单理解两者的关系就是:锁是面向使用者的;AQS面向的是锁的实现者,简化了锁的实现方式,屏蔽了同步状态管理,线程排队,等待唤醒底层操作的细节,对外放出模板方法供子类实现。
本质是通过java 语言自己实现的锁机制,通过一个状态标志+线程阻塞原语实现的锁。
————————————————
二、原理
state =0 资源空闲。>0 资源被占用。
node= 线程抽象。aqs中node 就是线程,将node 串起来==用双向链表实现一个CLH队列。
————————————————
核心方法:
//返回同步状态的当前值
protected final int getState() {
return state;
}
// 设置同步状态的值
protected final void setState(int newState) {
state = newState;
}
//原子地(CAS操作)将同步状态值设置为给定值update如果当前同步状态的值等于expect(期望值)
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
————————————————
isHeldExclusively()//该线程是否正在独占资源。只有用到condition才需要去实现它。
tryAcquire(int)//独占方式。尝试获取资源,成功则返回true,失败则返回false。
tryRelease(int)//独占方式。尝试释放资源,成功则返回true,失败则返回false。
tryAcquireShared(int)//共享方式。尝试获取资源。负数表示失败;0表示成功,但没有剩余可用资源;正数表示成功,且有剩余资源。
tryReleaseShared(int)//共享方式。尝试释放资源,成功则返回true,失败则返回false。
————————————————
——————进入方法解析——————————
final void lock() {
//cas操作设置state的值,如果state为0,则说明当前共享资源没有线程占用,设置为1,成功后设置独占线程为当前线程。
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
//如果state不为0,则说明有线程独占了,进入AQS核心方法,上图可见,随后进入tryAcquire方法
acquire(1);
}
/**
* Acquires in exclusive mode, ignoring interrupts. Implemented
* by invoking at least once {@link #tryAcquire},
* returning on success. Otherwise the thread is queued, possibly
* repeatedly blocking and unblocking, invoking {@link
* #tryAcquire} until success. This method can be used
* to implement method {@link Lock#lock}.
*
* @param arg the acquire argument. This value is conveyed to
* {@link #tryAcquire} but is otherwise uninterpreted and
* can represent anything you like.
*/
public final void acquire(int arg) {
//==判断1、是否为重入锁 !tryAcquire(arg)
// 2、不是重入锁 进行等待 acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
//进行线程中断
selfInterrupt();
}
//这是子类具体实现方法实现锁的逻辑,进入nonfairTryAcquire方法
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
//acquires = 1
final boolean nonfairTryAcquire(int acquires) {
//==这里又判断是否有资源
//获取当前线程
final Thread current = Thread.currentThread();
//获取state状态
int c = getState();
//如果状态为0,跟之前一样,则进入cas设置,并将独占线程设置为自己,返回true
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//==如果state不为0,且当前线程为独占线程,进行+1,也就是重入锁的实现。
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
//如果都不满足,表示既有独占线程,当前线程又不是独占线程,则要进入同步队列,等待锁的释放。这一步完进入AQS核心代码也就是第一个图
return false;
}
private Node addWaiter(Node mode) {
//将当前线程封装成Node节点。
Node node = new Node(Thread.currentThread(), mode);
// 尾交操作--
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
//如果是第一个节点,则进入enq方法
enq(node);
return node;
}
private Node enq(final Node node) {
//通过自旋的方式
//为啥用循环,cas操作的时候 可能会失败,自旋下
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
//这里用了 阻塞原语 进行 对线程阻塞 parkAndCheckInterrupt()
final boolean acquireQueued(final Node node, int arg) {
//标记是否成功拿到资源
boolean failed = true;
try {
//标记等待过程是否被中断
boolean interrupted = false;
//看到死循环就想到自旋
for (;;) {
//获取node的前序节点,这里目前是哨兵节点
final Node p = node.predecessor();
//如果前序节点是哨兵节点,则表示你是第二个,老二了,然后这里在尝试获取一次锁,如果成功
if (p == head && tryAcquire(arg)) {
//则将当前线程节点设置为哨兵节点
setHead(node);
//将之前的哨兵节点置成垃圾,方便gc
p.next = null; // help GC
//标识成功获取到资源
failed = false;
//表示线程未被中断
return interrupted;
}
//shouldParkAfterFailedAcquire方法判断线程是否需要等待,如果需要则返回true
//parkAndCheckInterrupt方法进行unsafe.park
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
//都满足后将状态设置为true,也就是中断线程
interrupted = true;
}
} finally {
//如果节点得不到资源,timeout了则进行中断资源的获取
if (failed)
cancelAcquire(node);
}
}
————————————————
解锁
public void unlock() {
//进入release方法
sync.release(1);
}
//AQS独占锁解锁核心代码
public final boolean release(int arg) {
//进入子类实现的解锁逻辑
//如果tryRelease返回true说明没有独占锁,否则好友线程持有
if (tryRelease(arg)) {
//当线程没有持有锁后,唤醒下一个线程执行
Node h = head;
//根据waitstatus判断需要唤醒哪个线程
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
//子类定义的解锁逻辑
protected final boolean tryRelease(int releases) {
//获取state - 1
int c = getState() - releases;
//判断当前线程是否是独占资源的线程
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
//设置资源是否还被独占着
boolean free = false;
//如果state = 0,表示没有线程独占
if (c == 0) {
//设置为true
free = true;
//当前独占线程置空
setExclusiveOwnerThread(null);
}
//cas设置state
setState(c);
return free;
}