查看 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;
    }

 

posted @ 2017-11-30 15:50  不怕万一的一万  阅读(167)  评论(0编辑  收藏  举报