1、类图 2、NonfairSync结构 3、流程图 4、重要方法源码解读
lock() final void lock() { //尝试用cas将state设置为1,设置成功则将exclusiveOwnerThread指向当前线程 if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else //cas设置state失败,说明当前锁有竞争 acquire(1); } acquire public final void acquire(int arg) { //尝试加锁,tryAcquire会成功会将state增加arg,state表示当前锁是否被别的线程持有 //0代表无其他线程持有该锁,大于0表示当前锁被持有,且数值大小为锁重入次数。 if (!tryAcquire(arg) && //将当前线程存入等待链表中 acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) //打断当前线程 selfInterrupt(); } 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) { //当前无线程持有锁,再次尝试获取锁 if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { //可重入设计,锁持有线程为当前线程 int nextc = c + acquires;//重入计数累加acquires if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); //设置重入数 setState(nextc); return true; } return false; } addWaiter private Node addWaiter(Node mode) { //创建引用当前线程的Node对象 Node node = new Node(Thread.currentThread(), mode); // 获取要加入Node对象的前驱节点(即还没加入当前Node的双向链表的尾节点) Node pred = tail; if (pred != null) { //pred 不为null,设置当前Node的前置节点为pred node.prev = pred; //设置尾节点为当前节点并建立双向连接 if (compareAndSetTail(pred, node)) { pred.next = node; return node; } } //没有任何前置节点,创建一个null引用的节点,并将其添加为当前节点的前驱节点。 //并建立双向连接。哑元设置为头节点,当前节点设置为尾节点 enq(node); return node; } acquireQueued 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)) { //成功获取锁 //该方法作用为设置头节点为当前节点,并且把当前节点的线程引用置null //把前置节点也置null setHead(node); //原前驱节点的后继节点置null,防止产生游离对象,GC无法正常回收 p.next = null; // help GC failed = false; return interrupted; } //不是首个节点或者首个节点获取锁失败,那么判断是否该阻塞这个线程,如果为true,那么阻塞当前线程。否则继续循环 if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; } } finally { if (failed) cancelAcquire(node); } } shouldParkAfterFailedAcquire private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) { int ws = pred.waitStatus; //判断前置节点是否为-1,-1表示解锁的时候该节点需要唤醒下一个节点 if (ws == Node.SIGNAL) /* * This node has already set status asking a release * to signal it, so it can safely park. */ //多次尝试获得锁失败,返回true尝试park当前线程 return true; if (ws > 0) { //waitStatus大于0表示当前节点的前驱节点放弃了任务执行 //接下来的操作就是遍历前驱节点的所有节点,直到找到等待状态不大于0的节点 do { node.prev = pred = pred.prev; } while (pred.waitStatus > 0); //设置状态不大于0的节点的后继节点为当前节点 pred.next = node; } else { //该方法只有初次调用时才会调用,作用是将前置节点的waitStatus置为-1,即第二次尝试shouldParkAfterFailedAcquire方法时会走第一个if,返回true,park当前线程。 compareAndSetWaitStatus(pred, ws, Node.SIGNAL); } return false; } parkAndCheckInterrupt private final boolean parkAndCheckInterrupt() { //暂停当前线程 LockSupport.park(this); //如果在park后因为interrupt()打断导致线程继续运行就返回true并清空打断标记 return Thread.interrupted(); }