查看 ReentrantLock 实现 源码 的理解记录!
ReentrantLock lock = new ReentrantLock(); lock.lock(); lock.unlock(); //ReentrantLock 源码中的使用 class X { //实例化 ReentrantLock时, //如果添加boolean参数, //true是公平模式, //flase是非公平模式, //默认非公平,非公平模式下新来的线程并不一定就能先拿到锁,后来的也并不一定是后拿到锁 ReentrantLock lock = new ReentrantLock(); public void m() { lock.lock(); try { // ... method body } finally { lock.unlock(); } } } //公平模式 下的lock,直接进行 acquire操作 final void lock() { acquire(1); } // 非公平模式 下的lock, //会先 根据 compareAndSetState 方法返回的结果, //去尝试把当前线程设置成为 独占所有者线程, //如果不成功再进行 acquire操作。 final void lock() { //compareAndSetState 根据cas 设置, //如果当前状态值等于期望值, //则将同步状态设置为给定的更新值。 //compareAndSetState(0, 1)) 预期值为0,修改值为1, //如果现在的state值为0,就把state值设置为1, //把当前线程设置独占所有。 if (compareAndSetState(0, 1)) //把当前线程设置为 独占所有者线程 setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); } //采用独占模式,忽略中断。
//处理没有获取到锁的线程
//tryAcquire:重新 获取 一次锁和进行锁重入的处理。
//addWaiter:将线程添加到 同步 队列中。
//acquireQueued:自旋 获取 锁。
//selfInterrupt:中断线程。
//三个条件的 为and,如果 acquireQueued方法 返回true,selfInterrupt会中断线程 public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt();//中断线程 } protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } //执行不公平的tryLock。 //tryAcquire是在子类中实现的,但都需要不公平的尝试trylock方法。 final boolean nonfairTryAcquire(int acquires) { //获取当前线程 final Thread current = Thread.currentThread(); //获取state的值 int c = getState(); //如果state的值为空,说明没有人使用锁 //如果预期值 为0,设置state为 设置值 if (c == 0) { if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } //如果state的值不是0,判断 独占所有者线程 是否为自己, //如果 独占所有者线程 是自己,state的值加上 要修改的值 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; } static final class Node { //指示节点在共享模式中等待的标记. static final Node SHARED = new Node(); //指示节点在独占模式中等待的标记. static final Node EXCLUSIVE = null; //同步队列中等待的线程等待超时或者被中断, //需要从同步队列中取消等待,节点进入该状态将不会变化 static final int CANCELLED = 1; //后继 结点的线程处于等待状态,而当前节点的线程如果释放了同步状态或者被取消, //将会通知后继节点,使后继节点的线程得以运行 static final int SIGNAL = -1; //节点在等待队列中,节点线程等待在Condition上, //当其他线程对Condition调用了Signal()方法后, //该节点将会从等待队列转移到同步队列中,加入到对同步状态的获取中 static final int CONDITION = -2; //表示下一次共享式同步状态获取将会无条件地被传播下去 static final int PROPAGATE = -3; //线程的等待状态volatile int waitStatus; volatile int waitStatus; } // 为当前线程和给定的模式创建节点 private Node addWaiter(Node mode) { Node node = new Node(Thread.currentThread(), mode); Node pred = tail; if (pred != null) { //如果 尾节点 不为null //设置当前新创建节点的 前驱 节点为 尾节点 node.prev = pred; //判断当前状态值是否等于预期的尾节点pred //如果 预期值 尾节点 等于就将当前同步状态值更新尾节点为node if (compareAndSetTail(pred, node)) { //尾节点的后继结点为 新创建的节点 pred.next = node; return node; } } enq(node); return node; } private Node enq(final Node node) { for (;;) { //获取尾节点 Node t = tail; if (t == null) { //初始化同步队列 // 创建新的节点new node()作为头节点 //把 头节点 作为尾节点 //而此时队列的尾节点和头结点是同一个节点 //由于enq是一个死循环,会再次进入判断 尾节点是否为空, //已经设置 头节点和尾节点,进入else语句 if (compareAndSetHead(new Node())) tail = head; } else { //尾节点不为空,把传入的node的 前驱 节点设置为尾节点 node.prev = t; if (compareAndSetTail(t, node)) { //判断node节点是否是预期的尾节点t,如果是就更新尾节点t为node, //把 t 的后继节点设置为 传入的节点,此时的 尾节点为 传入的node t.next = node; return t; } } } } //以死循环的方式不停的获取同步状态
//如果获取不到则阻塞节点中的线程, //而被阻塞线程只能依靠其前驱节点的出队列操作或者阻塞线程中断 final boolean acquireQueued(final Node node, int arg) { boolean failed = true; try { boolean interrupted = false; for (;;) { //获取 node节点的 前驱节点 final Node p = node.predecessor(); if (p == head && tryAcquire(arg)) { //如果传入node节点的前驱节点为head,并且 //当前 线程还能够获得到 锁,就把传入node节点,设置为head setHead(node); p.next = null; // help GC failed = false; return interrupted; } // shouldParkAfterFailedAcquire检查并更新未能获取的节点的状态 //parkAndCheckInterrupt 阻塞当前线程,暂停线程的轮询。
//当Unlock时会做后续节点的Unpark唤醒线程继续争抢锁。
if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) interrupted = true; } } finally { if (failed)//取消正在进行的获取尝试 cancelAcquire(node); } } //检查并更新未能获取的节点的状态,
//首先检查一下当前Node的前置节点pred是否是SIGNAL
//如果是SIGNAL,那么证明前置Node的线程已经Park了,
//如果waitStatus>0,那么当前节点已经Concel或者中断。
//那么不断调整当前节点的前置节点,将已经Concel的和已经中断的线程移除队列。
//如果waitStatus<0,那么设置waitStatus为SIGNAL,
//因为调用shouldParkAfterFailedAcquire的方法为死循环调用,所以终将返回true。 private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) { int ws = pred.waitStatus; if (ws == Node.SIGNAL) //如果线程阻塞,则返回true。 return true; if (ws > 0) { do { node.prev = pred = pred.prev; } while (pred.waitStatus > 0); pred.next = node; } else { //判断pred节点的waitStatus值,是否为预期的ws //如果是就更新 为 Node.SIGNAL,阻塞pred compareAndSetWaitStatus(pred, ws, Node.SIGNAL); } return false; }
lock.unlock(); public void unlock() { sync.release(1); } public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false; } private void unparkSuccessor(Node node) { int ws = node.waitStatus; if (ws < 0) compareAndSetWaitStatus(node, ws, 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); } protected final boolean tryRelease(int releases) { int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; if (c == 0) { free = true; setExclusiveOwnerThread(null); } setState(c); return free; }