ReentrantLock源码学习

113 阅读1分钟

ok,先看ReentrantLock实现的接口Lock,Lock中定义了锁必须要实现的方法,总共有六个,我们使用是一般使用锁的这六个方法基本就够用了

java.util.concurrent.locks.Lock#lock
java.util.concurrent.locks.Lock#lockInterruptibly
java.util.concurrent.locks.Lock#tryLock()
java.util.concurrent.locks.Lock#tryLock(long, java.util.concurrent.TimeUnit)
java.util.concurrent.locks.Lock#unlock
java.util.concurrent.locks.Lock#newCondition

接下来看下ReentrantLock的构造方法,只有两个

	private final Sync sync; //extends AbstractQueuedSynchornizer

    public ReentrantLock() { //无参构造,默认为非公平锁
        sync = new NonfairSync(); 
    }

    public ReentrantLock(boolean fair) { //带参构造,可以指定锁是公平的还是非公平的
        sync = fair ? new FairSync() : new NonfairSync();
    }

创建了对象后,就可以使用了

    public void lock() {
        sync.lock();
    }
    //直接看非公平锁的实现java.util.concurrent.locks.ReentrantLock.NonfairSync#lock
    final void lock() {
        if (compareAndSetState(0, 1)) //cas 修改state 的状态 ,成功就获取锁
            setExclusiveOwnerThread(Thread.currentThread());//设置占有锁的线程
        else
            acquire(1); //尝试获取锁
    }
    
    public final void acquire(int arg) {
    if (!tryAcquire(arg) &&
        acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) 
        selfInterrupt();//获取锁失败,并且加入队列失败
    }

java.util.concurrent.locks.AbstractQueuedSynchronizer#state记录了锁的状态,重入次数 java.util.concurrent.locks.AbstractQueuedSynchronizer#tryAcquire 是一个钩子方法,真正的实现在它的子类中java.util.concurrent.locks.ReentrantLock.NonfairSync#tryAcquire

      protected final boolean tryAcquire(int acquires) {
          return nonfairTryAcquire(acquires);
      }
      
      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); //重入次数加1
              return true;
          }
          return false;
    }

如果获取锁失败就会将线程加入到同步队列中排队acquireQueued(addWaiter(Node.EXCLUSIVE), arg)

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

java.util.concurrent.locks.AbstractQueuedSynchronizer#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)) { // 前驱为头节点,尝试获取锁
                    setHead(node); //获取成功,设置自己为头节点
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt()) //park当前线程
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

以上就是获取锁的过程,获取不到锁线程就会阻塞,接下来看下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;
    }
    
    protected final boolean tryRelease(int releases) {
        int c = getState() - releases; //重入次数
        if (Thread.currentThread() != getExclusiveOwnerThread())
            throw new IllegalMonitorStateException();
        boolean free = false;
        if (c == 0) { //重入次数为0
            free = true;
            setExclusiveOwnerThread(null); //释放锁
        }
        setState(c);
        return free;
    }
    
    private void unparkSuccessor(Node node) {
        /*
         * If status is negative (i.e., possibly needing signal) try
         * to clear in anticipation of signalling.  It is OK if this
         * fails or if status is changed by waiting thread.
         */
        int ws = node.waitStatus;
        if (ws < 0)
            compareAndSetWaitStatus(node, ws, 0);

        /*
         * Thread to unpark is held in successor, which is normally
         * just the next node.  But if cancelled or apparently null,
         * traverse backwards from tail to find the actual
         * non-cancelled successor.
         */
        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); // 唤醒线程
    }

Condition下次再学~