ReentrantLock 可重入锁 字面意思理解为同一线程可以重入加锁

AbstractQueuedSynchronizer 源码解析 可以先看这篇文章了解AQS原理
内部主要逻辑继承AQS来实现的,有两种实现FairSycn、NonfairSync,公平锁和非公平锁,默认为非公平锁。

  • 公平锁:保证先入队的先获得锁。
  • 非公平锁:不保证先入队的先获得锁,可能后面的线程先抢到锁。

image.png

主要实现流程

state值默认为0,当state=0时,线程通过CAS争抢锁,获取到锁时state值为1,同一个线程多次获取锁state值+1,解锁时-1直到为0时释放锁,未获取到锁的线程加入CLH队列阻塞LockSupport.park()等待,锁释放时通过CLH队列关联唤醒LockSupport.unpark()等待的线程去获取锁
image.png
CAS全名compare and swap比较交换,由native方法提供的系统原子性操作,以保证并发发安全性。

  • 公平锁的实现

    加锁

    //加锁
    final void lock() {
      acquire(1);//调用AQS方法
    }
    //AQS方法
    public final void acquire(int arg) {
      if (!tryAcquire(arg) &&//尝试获取锁,抽象方法由子类实现
          acquireQueued(addWaiter(Node.EXCLUSIVE), arg))    
          /* addWaiter 将线程加入等待队列
           * acquireQueued 尝试获取锁、阻塞
           */
      {
          //中断
          selfInterrupt();
      }
    }
    //尝试获取锁
    protected final boolean tryAcquire(int acquires) {
      //获取当前线程
      final Thread current = Thread.currentThread();
      int c = getState();//获取state值,AQS属性volatile标记
      if (c == 0) {//锁空闲状态
          if (!hasQueuedPredecessors() &&//是否需要排队
              compareAndSetState(0, acquires)) {//获取锁
              setExclusiveOwnerThread(current);//成功获取,设置锁owner为当前线程
              return true;//后续不在处理
          }
      }
      else if (current == getExclusiveOwnerThread()) {//当前线程已持有锁,重入
          int nextc = c + acquires;//state+1
          if (nextc < 0)
              throw new Error("Maximum lock count exceeded");
          setState(nextc);//已持有锁,直接设置state值
          return true;
      }
      return false;
    }

    解锁

    //解锁,ReentrantLock方法
    public void unlock() {
      sync.release(1);//AQS方法
    }
    //AQS解锁
    public final boolean release(int arg) {
      if (tryRelease(arg)) {//尝试解锁
          Node h = head;
          if (h != null && h.waitStatus != 0)//waitStatus=0时不进行unpark(唤醒),next线程可能中断
              unparkSuccessor(h);//唤醒队列中的线程去获取锁
          return true;
      }
      return false;
    }
    //尝试解锁ReentrantLock内部静态类Sync实现
    protected final boolean tryRelease(int releases) {
      int c = getState() - releases;//state-1
      if (Thread.currentThread() != getExclusiveOwnerThread())
          throw new IllegalMonitorStateException();//非持有锁的线程进行释放,非法操作
      boolean free = false;
      if (c == 0) {//持有锁线程全部释放
          free = true;
          setExclusiveOwnerThread(null);//持有锁线程置空
      }
      setState(c);//持有锁线程直接设置state
      return free;
    }
  • 非公平锁的实现

    非公平锁和公平锁的核心区别是在尝试获取锁方法tryAcquire实现中没有判断hasQueuedPredecessors()是否需要排队,其他逻辑和公平锁是一致的。
    image.png


lane
1 声望1 粉丝