1. lock方法
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
2. acquire方法
tryAcquire是尝试获取锁,判断state是否为0和是否是锁重入,是就返回true,不是就返回false接着下面判断
addWaiter是构造等待的队列,第一个是哨兵节点,其他是等待节点
acquireQueued传入当前node,通过不断循环判断,看是否是老二而且能够获得锁,能就返回打断值,看前一个节点是否是-1状态,是就执行等待方法,直到unpark或者打断,返回是否被打断
public final void acquire(int arg) {
if (!tryAcquire(arg) && // 尝试获取锁成功了方法就结束,失败了会进入下面的方法
acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) // 判断是否是老二和重试和...
selfInterrupt(); // 只有获取锁失败并且等待中时被打断了的才执行这个方法
}
2.1. tryAcquire方法
尝试获取锁,分三类,一类是state为0,用CAS实现第一次锁的获取,并且设置排他主节点,第二类是锁重入,将c+1,第三类就是其他线程抢不到锁,返回false
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
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);
return true;
}
return false;
}
2.1.1. addWaiter
该方法第一次建立队列用的是enq方法,以后都直接在if语句里面就return了,总体建立的是双向链表
方法返回值是新增的节点
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;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
2.2.1.1. enq
第一次建立队列用的方法,加哨兵节点
private Node enq(final Node node) {
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;
}
}
}
}
2.2. acquireQueued
获得的参数是addWaiter方法返回的新增的节点和 1
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
// 第三次循环如果抢到了是在tryAcquire中设置了node节点的线程为排他主节点
// 如果你的前一个节点是哨兵节点,说明你是即将获取锁的那位,再次重新获取一下锁
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
// p是当前节点的前置节点,node是当前节点
parkAndCheckInterrupt()) // 第一个是看看要不要park,第二个是执行park
interrupted = true;// 第二个方法来判断是否被打断的,是的话就会执行这行设置true
}
} finally {
if (failed)
cancelAcquire(node);
}
}
2.2.1. predecessor
返回值是调用节点的前一个节点
final Node predecessor() throws NullPointerException {
Node p = prev;
if (p == null)
throw new NullPointerException();
else
return p;
}
2.2.2. shouldParkAfterFailedAcquire
失败后是否要park
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL) // 如果是SIGNAL状态,即等待被占用的资源释放,直接返回true
return true;
if (ws > 0) { // ws大于0说明是CANCELLED状态
// 循环判断前驱节点的前驱节点是否也为CANCELLED状态,忽略该状态的节点,连接最后面<=0的节点
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
// 将当前节点的前驱节点设置为SIGNAL状态,用于后续唤醒操作
compareAndSetWaitStatus(pred, ws, Node.SIGNAL); // 0 -> -1
}
return false;
}
2.2.3. parkAndCheckInterrupt
上面判断失败后需要park后,这个方法就把这个node 挂起了
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this); // 在这个点就停下了,一直等待别人唤醒
// 1、被unpark
// 2、被中断(interrupt)
// 3、其他不合逻辑的返回才会继续向下执行
// 因上述三种情况程序执行到此,返回当前线程的中断状态,并清空中断状态
return Thread.interrupted(); // 如果由于被中断,该方法会返回true,其他返回false
}
2.2.4. setHead
private void setHead(Node node) {
head = node;
node.thread = null;
node.prev = null;
}
3. unlock
public void unlock() {
sync.release(1);
}
4. release
tryRelease是判断减去releases后状态为是否为0,是的话就是解锁了,不是说明还不应该放开锁
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h); // 该方法是设置头节点waitState为0和unpark下一个节点
return true;
}
return false;
}
4.1. tryRelease
该方法判断的是减去releases后状态为是否为0,是的话执行下面的unparkSuccessor方法
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
// 支持锁重入,只有state减为0,才释放成功
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
4.2. unparkSuccessor
执行unpark操作
private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0); // -1 -> 0
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
LockSupport.unpark(s.thread);
}