AQS的不公平锁源码
同步器节点的waitStatus解释 CANCELLED 取消状态 SIGNAL -1 等待触发状态,前节点可能是head或者前节点为取消状态CANCELLED CONDITION -2 等待条件状态,在等待队列中 PROPAGATE -3 状态需要向后传播 //不公平锁的lock函数 static final class NonfairSync extends Sync { private static final long serialVersionUID = 7316153563782823691L; /** * Performs lock. Try immediate barge, backing up to normal * acquire on failure. */ final void lock() { //首先尝试获得锁,如果获得,就将独占锁的内部变量改为当前线程 if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else //如果没有获得锁,就转到AQS类的acquire函数中 acquire(1); } protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } } //AQS类的acquire函数,传入参数1 public final void acquire(int arg) { if (!tryAcquire(arg) && //查看是否能够获得锁,就是上面的NonfairSync上面的tryAcquire方法,这个方法重写了虚类方法,如果不能,将返回false,查看&&后的方法 acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); } //ReentrantLock类的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; //计数器加一 if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; //这个时候的情况就是锁是被别的线程占领的 } //AQS类的addWaiter函数,传入参数Node.EXCLUSIVE private Node addWaiter(Node mode) { Node node = new Node(Thread.currentThread(), mode); // 用快速入列法试验一下 Node pred = tail; if (pred != null) { node.prev = pred; if (compareAndSetTail(pred, node)) { //cas操作设置尾节点 pred.next = node; return node; } } enq(node); //当cas操作不成,或者队列中没有别的线程的时候用这个 return node; } //AQS类的enq函数,传入参数等待假如阻塞队列的线程 private Node enq(final Node node) { //死循环,不加入不出来 for (;;) { Node t = tail; //获取尾节点 if (t == null) { // 如果尾节点是空,说明这个是第一个阻塞线程 if (compareAndSetHead(new Node())) //设置阻塞线程的头部,一个没有任何用处的头部 tail = head; //尾巴就是头,然后再次循环 } else { node.prev = t; if (compareAndSetTail(t, node)) { //cas操作将新的线程插入到tail,如果不成功将会再次循环过来 t.next = node; return t; //这个返回值在addWaiter函数中没有用 } } } } //通过调用addWaiter函数,AQS将当前线程加入到了等待队列,但是还没有阻塞当前线程的执行,接下来我们就来分析一下acquireQueued函数. //AQS类的acquireQueued函数,传入参数是已经加入到队列中的新的node节点 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)) { //如果新插入的这个节点是head节点的后面节点,说明新来的节点是将要获取锁的线程,尝试去获取锁 setHead(node); //将自己设置为头节点 p.next = null; // help GC //原来的节点next置空 failed = false; return interrupted; //因为没有被中断所以返回false } if (shouldParkAfterFailedAcquire(p, node) && //判断是否要进入阻塞状态.如果`shouldParkAfterFailedAcquire`返回true,表示需要进入阻塞 parkAndCheckInterrupt()) ////调用parkAndCheckInterrupt挂起线程,等待被唤醒 interrupted = true; } } finally { if (failed) cancelAcquire(node); } } //前面我们已经说过只有前一个节点pred的线程状态为SIGNAL时,当前节点的线程才能被挂起。 private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) { int ws = pred.waitStatus; if (ws == Node.SIGNAL) /* * This node has already set status asking a release * to signal it, so it can safely park. *前一个节点正在等待锁的释放,所以这个新的节点要阻塞 */ return true; if (ws > 0) { /* * Predecessor was cancelled. Skip over predecessors and * indicate retry. * 前一个节点处于取消获取独占性变量的状态,所以,可以跳过去,返回false */ do { node.prev = pred = pred.prev; } while (pred.waitStatus > 0); pred.next = node; } else { /* * waitStatus must be 0 or PROPAGATE. Indicate that we * need a signal, but don't park yet. Caller will need to * retry to make sure it cannot acquire before parking. */ compareAndSetWaitStatus(pred, ws, Node.SIGNAL); } return false; }