ReentrantLock源码

lock()

// 公平锁
final void lock() {
  acquire(1);
}


// 非公平锁
final void lock() {
  // CAS操作,尝试将state改成1。修改成功则该线程可以成功拿到锁。(原先state为0则说明无锁)
  if (compareAndSetState(0, 1))
    // 设置当前线程为锁的拥有者
    setExclusiveOwnerThread(Thread.currentThread());
  else
    // CAS没修改成功,则说明锁被占用,这是和公平锁一样,调用该方法
    acquire(1);
}

acquire()

public final void acquire(int arg) {
  // 1.调用tryAcquire方法获取锁资源,成功返回true,结束该方法
  if (!tryAcquire(arg) &&
      // 2.1 没获取到锁,执行addWaiter此方法,将没获取到锁的线程封装成Node对象,插入到AQS的队列尾部作为tail
      // 2.2 调用acquireQueued方法,查看当前的Node是否排在队列前面,即(head的next),是的话尝试获取锁资源,否则挂起线程
      acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
    // 设置当前线程中断标志位
    selfInterrupt();
}

tryAcquire()

// AQS实现,AQS是基类,这里只提供方法,具体子类实现。(用了设计模式的 模板方法)
protected boolean tryAcquire(int arg) {
  throw new UnsupportedOperationException();
}

// 公平锁
protected final boolean tryAcquire(int acquires) {
  // 获取当前线程
  final Thread current = Thread.currentThread();
  // 获取state的值
  int c = getState();
  // state值为0,则说明锁空闲。
  if (c == 0) {
    // state值为0,判断队列是否有线程在排队,如果有线程在排队,则直接结束方法,返回最外层的false
    if (!hasQueuedPredecessors() &&
        // 没有线程在排队,CAS操作,尝试将state改成1。修改成功则该线程可以成功拿到锁。(原先state为0则说明无锁)
        compareAndSetState(0, acquires)) {
      // state值为0,无线程排队,CAS操作成功,该线程可以成功拿到锁
      setExclusiveOwnerThread(current);
      return true;
    }
  }
  // state值不为0,判断当前线程是否是锁的占有者
  else if (current == getExclusiveOwnerThread()) {
    // 是锁的占有者,state + 1
    int nextc = c + acquires;
    // int类型的最高位是符号位,这里判断小于0的话,则超过最大重入数,直接抛异常
    if (nextc < 0)
      throw new Error("Maximum lock count exceeded");
    // 锁重入没有超过最大值的话,则设置锁重入数
    setState(nextc);
    return true;
  }
  return false;
}

//非公平
final boolean nonfairTryAcquire(int acquires) {
  // 拿到当前线程
  final Thread current = Thread.currentThread();
  // 拿到state值
  int c = getState();
  // state为0说锁空闲,之前抢一波(不管有没有在队列里排队)
  if (c == 0) {
    // CAS操作,尝试将state改成1。修改成功则该线程可以成功拿到锁。(原先state为0则说明无锁)
    if (compareAndSetState(0, acquires)) {
      // 设置当前线程为锁的拥有者
      setExclusiveOwnerThread(current);
      return true;
    }
  }
  // state不为0说明锁被占用。判断占用锁的线程是否为当前线程(是的话锁重入)
  else if (current == getExclusiveOwnerThread()) {
    // 锁的占有者是当前线程,则state + 1
    int nextc = c + acquires;
    // int类型的最高位是符号位,这里判断小于0的话,则超过最大重入数,直接抛异常
    if (nextc < 0) // overflow
      throw new Error("Maximum lock count exceeded");
    // 锁重入没有超过最大值的话,则设置锁重入数
    setState(nextc);
    return true;
  }
  return false;
}

addWaiter()

// 将当前节点插入队列末尾,作为尾节点
private Node addWaiter(Node mode) {
  // 创建当前线程为节点,mode为null则代表是互斥锁
  Node node = new Node(Thread.currentThread(), mode);
  // 创建对象prde指向尾节点,即pred此时是尾节点
  Node pred = tail;
  // 尾节点不空执行
  if (pred != null) {
    // 要插入的节点的前指针指向原先的尾节点
    node.prev = pred;
    // CAS将要插入的节点设置为尾节点
    if (compareAndSetTail(pred, node)) {
      // 原尾节点的后指针指向要插入的节点,返回尾节点(要插入的节点)
      pred.next = node;
      return node;
    }
  }
  // 尾节点为空或者CAS失败,执行enq方法
  enq(node);
  return node;
}

enq()

// 循环插入节点
private Node enq(final Node node) {
  for (;;) {
    // 创建对象t,指向尾节点(t此时就是尾节点)
    Node t = tail;
    // 尾节点为空
    if (t == null) { 
      // CAS 初始化头节点、尾节点
      if (compareAndSetHead(new Node()))
        tail = head;
    } else {
      // 尾节点不空,将要插入的节点的前指针指向原先的尾节点
      node.prev = t;
      // CAS将要插入的节点设置为尾节点
      if (compareAndSetTail(t, node)) {
        // 原尾节点的后指针指向要插入的节点,返回尾节点(要插入的节点)
        t.next = node;
        return t;
      }
    }
  }
}

acquireQueued()

final boolean acquireQueued(final Node node, int arg) {
  // 定义变量,失败标识为true
  boolean failed = true;
  try {
    boolean interrupted = false;
    for (;;) {
      // 创建对象p为当前节点的上一个节点
      final Node p = node.predecessor();
      // 如果上一个节点为头节点 并且 tryAcquire方法成功获取锁资源
      if (p == head && tryAcquire(arg)) {
        // 设置当前节点为头节点
        setHead(node);
        // 上一个节点的后指针指向空(这样根可达分析算法就关联不到它,就会被当作垃圾回收)
        p.next = null;
        // 失败标识改为false,即获取锁成功
        failed = false;
        return interrupted;
      }
      // 如果上一个节点不是头节点 或者 tryAcquire方法没有获取到锁资源
      // 判断上一个节点的状态是否正常,不正常方法结束
      // CANCELLED =  1; 代表锁取消,例如tryLock()设置时间过期了
      // SIGNAL    = -1; 代表锁正常
      // CONDITION = -2; 代表lock里面的类似wait()的作用,锁正常
      // PROPAGATE = -3; 代表共享锁,锁正常
      if (shouldParkAfterFailedAcquire(p, node) &&
          // 上一个节点正常,将线程挂起(通过LockSupport将当前线程挂起)
          parkAndCheckInterrupt())
        interrupted = true;
    }
  } finally {
    if (failed)
      cancelAcquire(node);
  }
}

shouldParkAfterFailedAcquire()

// 如果上一个节点不是头节点 或者 tryAcquire方法没有获取到锁资源
// 判断上一个节点的状态是否正常,不正常方法结束
// CANCELLED =  1; 代表锁取消,例如tryLock()设置时间过期了
// SIGNAL    = -1; 代表锁正常
// CONDITION = -2; 代表lock里面的类似wait()的作用,锁正常
// PROPAGATE = -3; 代表共享锁,锁正常
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
  // 获取上一个节点的状态
  int ws = pred.waitStatus;
  // 上一个节点状态为-1,则节点正常,返回true
  if (ws == Node.SIGNAL)
    return true;
  // 上一个节点状态为 > 0,即只有为1,则上一个节点无效(非正常)
  if (ws > 0) {
    // 循环 从当前节点往前找,找到第一个正常节点,将正常节点的后指针指向当前节点
    do {
      node.prev = pred = pred.prev;
    } while (pred.waitStatus > 0);
    // 找到第一个正常节点,将正常节点的后指针指向当前节点
    pred.next = node;
  } else {
    // 上一个节点状态 <= 0,CAS将上一个节点状态改为-1
    compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
  }
  // 上一个节点状态不正常,返回false
  return false;
}

unlock()

// 释放锁
public void unlock() {
  sync.release(1);
}

release()

// 判断释放锁是否成功
public final boolean release(int arg) {
  // 调用tryRelease方法尝试释放锁资源
  if (tryRelease(arg)) {
    // 释放锁成功,创建对象指向头节点(即h为头节点)
    Node h = head;
    // 头节点不为空 且 头节点的状态不为0,则唤醒排队的线程
    if (h != null && h.waitStatus != 0)
      // 
      unparkSuccessor(h);
    return true;
  }
  return false;
}

tryRelease()

// 核心方法,尝试释放锁
protected final boolean tryRelease(int releases) {
  // state - 1
  int c = getState() - releases;
  // 当前线程 不等于 占有锁的线程,抛出异常
  if (Thread.currentThread() != getExclusiveOwnerThread())
    throw new IllegalMonitorStateException();
  // 定义释放锁是否成功标志,默认不成功
  boolean free = false;
  // state = 0说明,没有重入锁了
  if (c == 0) {
    // 将释放锁标志置为成功
    free = true;
    // 将锁的占有者置为空
    setExclusiveOwnerThread(null);
  }
  // 给state赋值
  setState(c);
  // 返回锁是否释放成功的标志
  return free;
}

unparkSuccessor()

// 唤醒头节点
private void unparkSuccessor(Node node) {
  // 获取当前节点的状态
  int ws = node.waitStatus;
  // 当前节点状态 < 0,即锁正常
  if (ws < 0)
    // CAS将节点的状态置为0 (这里对于ReentranLock来说没啥用)
    compareAndSetWaitStatus(node, ws, 0);
  // 创建对象指向 下一个节点
  Node s = node.next;
  // 下一个节点为空 或者 下一个节点的状态 > 0 则下一个节点无效(非正常)
  if (s == null || s.waitStatus > 0) {
    // 将下一节点置为空,即下一个节点不需要唤醒,需唤醒下一个节点的下一个节点
    s = null;
    // 从尾部往前遍历,找到第一个正常节点
    for (Node t = tail; t != null && t != node; t = t.prev)
      // 如果状态 <= 0则为正常节点
      if (t.waitStatus <= 0)
        s = t;
  }
  // 通过遍历获取到的第一个正常节点不为空,唤醒线程
  if (s != null)
    // 唤醒线程
    LockSupport.unpark(s.thread);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值