在分析AbstractQueuedSynchronizer时,我们先从ReentrantLock重入锁代入。
ReentrantLock主要有三个内部类:FairSync,NonfairSync, Sync
使用场景:
//通过这个重入锁使用场景来进入到AQS中
public class ReentrantLockTest {
static ReentrantLock rl = new ReentrantLock();
public static void main(String[] args) {
for (int i = 0; i < 4; i++) {
new Thread(()->{
try {
// 1.我们从这个lock入手
rl.lock();
System.out.println(Thread.currentThread().getName()+":lock");
System.out.println("ThreadName="+Thread.currentThread().getName());
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
rl.unlock();
System.out.println(Thread.currentThread().getName()+":unlock");
}
},"Thread"+i).start();
}
}
}
我们现在来研究一下lock方法。
//1.调用ReentrantLock 的lock方法
public void lock() {
//调用sync内部类的lock()方法
sync.lock();
}
// 默认调用非公平类
/**
* Sync object for non-fair locks
*/
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
// 2.进入lock方法
final void lock() {
if (compareAndSetState(0, 1)) //通过cas判断当前线程status是否为0,是则将status置为1,并返回true
setExclusiveOwnerThread(Thread.currentThread()); //当前线程获得锁
else
acquire(1); //生成阻塞队列,我们在第3步对此方法进行详细分解
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
// 3 获得
public final void acquire(int arg) {
if (!tryAcquire(arg) && //尝试获取锁
acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) //生产阻塞队列
selfInterrupt();
}
//接下来!tryAcquire(arg) && //尝试获取锁
// acquireQueued(addWaiter(Node.EXCLUSIVE), arg)
//我们做2步进行分解
//3.1 我们对3中的tryAcquire()方法进行分析
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires); //调用nonfairTryAcquire()方法
}
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread(); //获取当前线程
int c = getState(); //获取当前线程状态
if (c == 0) { //当状态为0时进入
if (compareAndSetState(0, acquires)) { //判断当前线程状态是否为0,为0则将状态设为acquires,并返回true
setExclusiveOwnerThread(current); //当前线程获得锁
return true;
}
}
else if (current == getExclusiveOwnerThread()) { //当当前线程为锁拥有者时进入
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);//设置当前线程状态为c + acquires;
return true;
}
return false;
}
}
//3.2 对acquireQueued(addWaiter(Node.EXCLUSIVE), arg)
//我们先对addWaiter(Node.EXCLUSIVE), arg)进行分析,此处为创建双向链表
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode); //创建一个空节点
// Try the fast path of enq; backup to full enq on failure
Node pred = tail; //tail=null
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) { //cas判断tail是否等于node的前一节点,是则将tail指向tail
pred.next = node;
return node;
}
}
enq(node); //自旋
return node;
}
//3.2.1 我们对enq(node)进行分析
private Node enq(final Node node) {
for (;;) {
Node t = tail; //将tail赋值给t
if (t == null) { // 初始化
if (compareAndSetHead(new Node())) //将将head指向new Node()
tail = head; //此时tail和head都指向new Node()
} else {
node.prev = t;
if (compareAndSetTail(t, node)) { //将tail指向node
t.next = node;
return t;
}
}
}
}
下图为addWaiter双向链表的生成。
接下来我们对acquireQueued(addWaiter(Node.EXCLUSIVE), arg)中的acquireQueued()方法进行解析
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor(); //获得当前节点的前一节点p
if (p == head && tryAcquire(arg)) { //当前一节点为head,则尝试去获取锁,如果获得,则进入
setHead(node);//将当前节点设置为头节点
p.next = null; // 将p节点的next指向初始化
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) && //将状态设置为SIGNAL
parkAndCheckInterrupt())//将线程阻塞
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node); //如果失败,则取消
}
}
我写这个主要就是想分享一下双向链表生成。