AQS: 全称是AbstractQueuedSynchronizier,抽象队列同步器;他是各种同步工具锁的基础,比如ReentrantLock, CyclicBairier都是基于AQS来实现的。
以AtomicInteger为例子来分析一下CAS的应用。
首先看内部结构:
public static class AtomicBTreePartition{
private volatile long lock;
private static final AtomicLongFieldUpdater
lockFieldUpdater
=AtomicLongFieldUpdater
.newUpdater(AtomicBTreePartition.class,"lock");
public void acquireLock(){
long t = Thread.currentThread().getId();
while (!lockFieldUpdater.compareAndSet(this, 0, 1)){
//数据库操作
}
}
public void releaseLock(){
}
}
她的组成核心主要有3个部分。
下面以ReentrantLock的非公平锁为例,分析一下它的加锁和释放锁的实现。
加锁操作代码:
public void lock() {
sync.acquire(1);
}
继续跟进:
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
非公平锁的获取锁操作:
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();// 获取当前AQS内部状态量
if (c == 0) {
// 0表示无人占有,则直接用CAS修改状态位,
if (compareAndSetState(0, acquires)) {
// 不检查排队情况,直接争抢
setExclusiveOwnerThread(current);
//并设置当前线程独占锁
return true;
}
} else if (current == getExclusiveOwnerThread()) {
//即使状态不是0,也可能当前线程是锁持有者,因为这是再入锁
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
排队竞争:
final boolean acquireQueued(final Node node, int arg) {
boolean interrupted = false;
try {
for (;;) {// 循环
final Node p = node.predecessor();// 获取前一个节点
if (p == head && tryAcquire(arg)) {
// 如果前一个节点是头结点,表示当前节点合适去tryAcquire
setHead(node); // acquire成功,则设置新的头节点
p.next = null; // 将前面节点对当前节点的引用清空
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node))
// 检查是否失败后需要park
interrupted |= parkAndCheckInterrupt();
}
} catch (Throwable t) {
cancelAcquire(node);// 出现异常,取消
if (interrupted)
selfInterrupt();
throw t;
}
本节介绍了CAS和AQS的概念,然后以AtomicInteger为例切入原子操作是怎么利用CAS来保证的。
最后,以ReentrantLock的加锁操作,跟进了是如何利用AQS来保证内部的不同操作的。
算是初步探究了同步的实现原理。
原创不易,转载请注明出处,让我们互通有无,共同进步,欢迎多沟通交流