> 文档中心 > 多线程之ReentrantLock

多线程之ReentrantLock


ReentrantLock

lock

  1. lock调用ReentrantLock中lock调用sync.acquire
/** Synchronizer providing all implementation mechanics */private final Sync sync;public void lock() {    sync.acquire(1);}
  1. sync.acquire(1)则调用AbstractQueuedSynchronizer(AQS)下的acquire方法
public final void acquire(int arg) {    if (!tryAcquire(arg) && //如果没有上锁,则将线程放入等待队列中 acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt();}
  1. 将线程放入等待队列中的两个方法acquireQueued与addWaiter

先看addWaiter

/** * Creates and enqueues node for current thread and given mode. * * @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared * @return the new node * 为当前线程和给定模式创建和排队节点。 * 参数:模式– Node.EXCLUSIVE 用于独占,Node.SHARED 用于共享 * 返回:新节点 */private Node addWaiter(Node mode) {    //创建一个新节点    Node node = new Node(mode);//直到加入队列为止    for (;;) { //将尾节点用一个节点存储下来 Node oldTail = tail; //将新节点加入链表尾部 if (oldTail != null) {     node.setPrevRelaxed(oldTail);     if (compareAndSetTail(oldTail, node)) {  oldTail.next = node;  return node;     } } else {     initializeSyncQueue(); }    }}
/** * Acquires in exclusive uninterruptible mode for thread already in * queue. Used by condition wait methods as well as acquire. * * @param node the node * @param arg the acquire argument * @return {@code true} if interrupted while waiting * 以独占不间断模式获取已在队列中的线程。由条件等待方法和获取使用。 * 参数:节点——节点arg – 获取参数 * 回报:如果在等待时被打断,则为true */final boolean acquireQueued(final Node node, int arg) {    boolean interrupted = false;    try { for (;;) {     //获取该节点的前驱节点     final Node p = node.predecessor();     //判断是否是头节点,并尝试获取锁,等第一个节点释放锁就能获取锁     if (p == head && tryAcquire(arg)) {  setHead(node);  p.next = null; // help GC  return interrupted;     }     if (shouldParkAfterFailedAcquire(p, node))  interrupted |= parkAndCheckInterrupt(); }    } catch (Throwable t) { cancelAcquire(node); if (interrupted)     selfInterrupt(); throw t;    }}
  1. 然后调用ReentrantLock中的静态内部类NonfairSync中tryAcquire,继承于Sync
static final class NonfairSync extends Sync {    private static final long serialVersionUID = 7316153563782823691L;    protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires);    }}
  1. 然后调用ReentrantLock中静态内部类Sync中的nonfairTryAcquire方法,该类继承于AbstractQueuedSynchronizer
/** * Performs non-fair tryLock.  tryAcquire is implemented in * subclasses, but both need nonfair try for trylock method. * 执行不公平的 tryLock。 tryAcquire 在子类中实现,但两者都需要对 trylock 方法进行非公平尝试。 */@ReservedStackAccessfinal boolean nonfairTryAcquire(int acquires) {    //获取当前线程    final Thread current = Thread.currentThread();    //获取当前线程的状态,看是否上锁    int c = getState();    //判断当前线程是否上锁    if (c == 0) { //将当前线程的状态从0-》1 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); return true;    }    return false;}

lock流程过程图

在这里插入图片描述

ReentrantLock的lock调用流程如下:

  1. 调用ReentrantLock中的lock方法,而lock方法中语句sync.acquire()调用AbstractQueuedSynchronizer类中的acquire()方法
  2. acquire() 方法调用ReentrantLock中的静态内部类NonfairSync中的tryAcquire(arg)方法,类NonfairSync继承于Sync类
  3. tryAcquire方法中代用Sync类中的nonfairTryAcquire()方法,主要用于设置必要的参数

unlock

  1. 第一步调用unlock,调用Sync中的release方法
/** Synchronizer providing all implementation mechanics */private final Sync sync;/** * Attempts to release this lock. * * 

If the current thread is the holder of this lock then the hold * count is decremented. If the hold count is now zero then the lock * is released. If the current thread is not the holder of this * lock then {@link IllegalMonitorStateException} is thrown. * * @throws IllegalMonitorStateException if the current thread does not * hold this lock */public void unlock() { //释放一个 sync.release(1);}

  1. 第二步: sync.release(1);调用AQS中的release方法
/** * Releases in exclusive mode.  Implemented by unblocking one or * more threads if {@link #tryRelease} returns true. * This method can be used to implement method {@link Lock#unlock}. * * @param arg the release argument.  This value is conveyed to * {@link #tryRelease} but is otherwise uninterpreted and * can represent anything you like. * @return the value returned from {@link #tryRelease} */public final boolean release(int arg) {    //尝试将持有当前锁的对象给释放掉    if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0)     //如果没有将当前线程释放掉,则将查找本线程在链表中的下一个节点,将其唤醒去抢占锁     unparkSuccessor(h); return true;    }    return false;}
  1. 如果没有将当前线程释放掉,则将查找本线程在链表中的下一个节点,将其唤醒去抢占锁
/** * Wakes up node's successor, if one exists. * 唤醒节点的后继者(如果存在)。 * 参数:节点——节点 * @param node the node */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) node.compareAndSetWaitStatus(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 p = tail; p != node && p != null; p = p.prev)     if (p.waitStatus <= 0)  s = p;    }    if (s != null) LockSupport.unpark(s.thread);}
  1. 第三步:调用ReentrantLock中的tryRelease尝试将其释放
@ReservedStackAccessprotected final boolean tryRelease(int releases) {    //将当前线程状态减1    int c = getState() - releases;    //判断是否是当前线程所占的锁    if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException();    boolean free = false;    if (c == 0) { free = true; //设置对当前独占访问权限者为null setExclusiveOwnerThread(null);    }    setState(c);    return free;}
/*** 设置当前拥有独占访问权限的线程。 null参数表示没有线程拥有访问权限。此方法不会强加任何同步或volatile字段访 * 问。* 参数:线程——所有者线程*/protected final void setExclusiveOwnerThread(Thread thread) {    exclusiveOwnerThread = thread;}

unlock流程过程图

在这里插入图片描述