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.2.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); }