ReentrantLock 源码解析

ReentrantLock 源码解析

ReentrantLock 类描述

一种可重入互斥锁 Lock ,与使用 synchronized 方法和语句访问的隐式监控锁具有相同的基本行为和语义,但具有扩展的功能。

  • 一个 ReentrantLock 被上次成功锁住但还没有解锁的线程拥有,当锁不属于其他线程时,调用 lock() 的线程将成功地获取锁返回。如果当前线程已经拥有锁,该方法将立即返回。这可以通过方法 isHeldByCurrentThread() 和 getHoldCount() 来检查。

  • 这个类的构造函数接受一个可选参数 fairness 。当设置 true 时,在争用的情况下,锁有利于授予访问等待时间最长的线程的访问权。否则,此锁不能保证任何特定的访问顺序。使用由多个线程访问的公平锁的程序可能显示出较低的总体吞吐量(即,较慢;通常比使用默认设置的慢得多),但获得锁的时间差异较小,并保证不会出现“饥饿”现象。但是要注意,锁的公平性并不保证线程调度的公平性。。因此,使用公平锁的多个线程中的一个可以连续多次获得该锁,而其他活动线程目前没有在进行操作,也没有持有该锁。

    还要注意,不定时的 tryLock() 方法不遵守公平性设置。如果锁可用,即使其他线程正在等待,它也会成功。

  • 建议在调用 lock() 后总是紧跟 try 块,最典型的是在before - after结构中,例如:

    class X {
      private final ReentrantLock lock = new ReentrantLock();
      // ...
      public void m() {
        lock.lock();  // block until condition holds
        try {
          // ... method body
        } finally {
          lock.unlock()
        }
      }
    }
    
  • 除了实现 Lock() 接口之外,这个类还定义了 public 和 protected 两个方法,用于检查锁的状态。其中一些方法只对检测和监控有用。

  • 这个类的序列化与内置锁的行为相同:反序列化的锁处于未锁定状态,无论序列化时的状态如何。

  • 同一个线程最多支持2147483647个递归锁。如果超过这个限制,锁定方法会抛出 Error 。

ReentrantLock 源码

public class ReentrantLock implements Lock, Serializable {
    private static final long serialVersionUID = 7373984872572414699L;
    /** Synchronizer providing all implementation mechanics */
    private final Sync sync;

    /**
     * 此锁的同步控制基础。分为以下公平和非公平版本。使用AQS状态表示锁的保持数。
     */
    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;

        abstract void lock();

        /**
         * 非公平,尝试获取锁(现场时获取锁,获取失败进入队列)
         */
        final boolean nonfairTryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            // c=0 表示当前锁未被其他线程持有
            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);
                return true;
            }
            //获取锁失败 false
            return false;
        }


        /**
         * 释放锁:(返回是否完全释放锁了的)
         * 如果当前线程是此锁的持有者,那么将减少持有者计数。
         * 如果保持计数现在为零,则解除锁定。
         * 如果当前线程不是此锁的持有者,则抛出{@link IllegalMonitorStateException}。
         */
        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);
            }
            //锁重入的情况下,释放锁,只是  state - 1
            setState(c);
            return free;
        }

        /**
         * 判断当前线程是否是持有锁的线程
         */
        protected final boolean isHeldExclusively() {
            return getExclusiveOwnerThread() == Thread.currentThread();
        }

        final ConditionObject newCondition() {
            return new ConditionObject();
        }
        
        // ========================= 从外部类传递的方法 =============================
        // Methods relayed from outer class

        /**
         * 获取锁的持有线程
         */
        final Thread getOwner() {
            return getState() == 0 ? null : getExclusiveOwnerThread();
        }
        
        /**
         * 获取锁的保持数
         */
        final int getHoldCount() {
            return isHeldExclusively() ? getState() : 0;
        }

        /**
         * 锁是否被线程持有
         */        
        final boolean isLocked() {
            return getState() != 0;
        }

        /**
         * 从流中重新构造实例(即反序列化)。
         */
        private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {
            s.defaultReadObject();
            setState(0); // reset to unlocked state
        }
    }

    /**
     * 非公平锁的同步对象
     */
    static final class NonfairSync extends Sync {
        private static final long serialVersionUID = 7316153563782823691L;

        /**
         * 先尝试设置锁的状态值(争抢锁),获取锁成功,则持有锁返回
         */
        final void lock() {
            //先尝试设置锁的状态值(争抢锁),获取锁成功,则持有锁返回
            if (compareAndSetState(0, 1))
                setExclusiveOwnerThread(Thread.currentThread());
            else
                acquire(1);//获取锁失败,进入等待队列
        }

        protected final boolean tryAcquire(int acquires) {
            return nonfairTryAcquire(acquires);
        }
    }

    /**
     * 公平锁的同步对象
     */
    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;

        final void lock() {
            acquire(1);
        }

        /**
         * tryAcquire的公平版本。除非递归调用、没有等待或是第一个,否则不要授予访问权限
         */
        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            // c=0 表示当前锁未被其他线程持有
            if (c == 0) {
                //判断等待队列的为空,为空则尝试设置值,获取锁
                if (!hasQueuedPredecessors() &&
                    compareAndSetState(0, acquires)) {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            // current = getExclusiveOwnerThread() 表示 锁重入,state + 1
            else if (current == getExclusiveOwnerThread()) {
                int nextc = c + acquires;
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            // 获取锁失败,后续根据 false 值,进入等待队列
            return false;
        }
    }

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

    /**
     * 根据参数判断 构建:公平(true)或非公平锁(false)
     */
    public ReentrantLock(boolean fair) {
        sync = fair ? new FairSync() : new NonfairSync();
    }

    /**
     * 获取锁。
     * 如果锁没有被其他线程持有,则获取锁并立即返回,将锁持有计数设置为 1。
     * 如果当前线程已经持有锁,那么持有计数加1,该方法立即返回。
     * 如果锁被另一个线程持有,那么当前线程将无法进行线程调度,并处于休眠状态,直到获得锁,此时锁保持计数设置为1。
     */
    public void lock() {
        sync.lock();
    }

    /**
     * 除非当前线程是 interrupted,否则获取锁。
     * 1.如果另一个线程未持有锁,则获取该锁并立即返回,将锁持有计数设置为1。
     * 2.如果当前线程已经持有该锁,则持有计数将增加1,方法将立即返回。
     * 3.如果锁由另一个线程持有,则当前线程出于线程调度目的而被禁用,并处于休眠状态,直到发生以下两种情况之一:锁由当前线程获取 或 其他线程中断当前线程。
     * 4.如果当前线程获取了锁,则锁保持计数设置为1。
     * 5.如果当前线程:在进入该方法时设置其中断状态;或在获取锁时被中断。则抛出{@link InterruptedException},并清除当前线程的中断状态
     * 在这个实现中,由于该方法是一个显式中断点,因此优先考虑响应中断,而不是正常或可重入获取锁。
     */
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    /**
     * 尝试获取锁
     * 仅当锁在调用时没有被另一个线程持有时,才获取锁。
     * 1.如果锁没有被其他线程持有,则获取锁,并立即返回值为  true ,将锁持有次数设置为1。 即使该锁被设置为使用公平排序策略,如果锁可用,调用  tryLock() 将立即获得锁,无论其他线程是否正在等待该锁。
     *  这个 barging; 行为在某些情况下是有用的,即使它破坏了公平。如果您想遵守此锁的公平性设置,则使用  tryLock(long, TimeUnit) tryLock(0, TimeUnit. seconds),这几乎是等效的(它还检测中断)。
     * 2.如果当前线程已经持有此锁,则持有计数将增加1,方法返回 true
     * 3.如果锁由另一个线程持有,则此方法将立即返回值 false。
     */
    public boolean tryLock() {
        return sync.nonfairTryAcquire(1);
    }

    /**
     * 给定时间内尝试获取锁,获取是否成功,都需要返回获取锁的情况
     */
    public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }

    /**
     * 释放锁
     *
     * 如果当前线程是此锁的持有者,那么将减少持有者计数。
     * 如果保持计数现在为零,则解除锁定。
     * 如果当前线程不是此锁的持有者,则抛出{@link IllegalMonitorStateException}。
     */
    public void unlock() {
        sync.release(1);
    }

    /**
     * 创建一个 等待条件
     */
    public Condition newCondition() {
        return sync.newCondition();
    }

    /**
     *  查询当前线程对此锁的保留数。
     */
    public int getHoldCount() {
        return sync.getHoldCount();
    }

    /**
     *  查询当前线程是否持有此锁。
     */
    public boolean isHeldByCurrentThread() {
        return sync.isHeldExclusively();
    }

    /**
     *  查询此锁是否由任何线程持有。该方法设计用于监控系统状态,而不是用于同步控制。
     */
    public boolean isLocked() {
        return sync.isLocked();
    }

    /**
     * 判断是否是公平锁
     */
    public final boolean isFair() {
        return sync instanceof FairSync;
    }

    /**
     * 返回当前持有锁的线程
     */
    protected Thread getOwner() {
        return sync.getOwner();
    }

    /**
     * 判断等待队列是否为空
     */
    public final boolean hasQueuedThreads() {
        return sync.hasQueuedThreads();
    }

    /**
     * 判断当前等待队列中是否包含 某一个线程
     */
    public final boolean hasQueuedThread(Thread thread) {
        return sync.isQueued(thread);
    }

    /**
     * 获取等待队列的长度
     */
    public final int getQueueLength() {
        return sync.getQueueLength();
    }

    /**
     * 获取等待队列中的所有线程
     */
    protected Collection<Thread> getQueuedThreads() {
        return sync.getQueuedThreads();
    }

    /**
     * 判断是否有 等待某一个条件 的线程
     */
    public boolean hasWaiters(Condition condition) {
        if (condition == null)
            throw new NullPointerException();
        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
            throw new IllegalArgumentException("not owner");
        return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
    }

    /**
     * 获取等待 某个条件的 等待队列长度
     */
    public int getWaitQueueLength(Condition condition) {
        if (condition == null)
            throw new NullPointerException();
        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
            throw new IllegalArgumentException("not owner");
        return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
    }

    /**
     * 获取等待 某一个条件的  所有线程
     */
    protected Collection<Thread> getWaitingThreads(Condition condition) {
        if (condition == null)
            throw new NullPointerException();
        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
            throw new IllegalArgumentException("not owner");
        return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
    }

    /**
     * Returns a string identifying this lock, as well as its lock state.
     * The state, in brackets, includes either the String {@code "Unlocked"}
     * or the String {@code "Locked by"} followed by the
     * {@linkplain Thread#getName name} of the owning thread.
     *
     * @return a string identifying this lock, as well as its lock state
     */
    public String toString() {
        Thread o = sync.getOwner();
        return super.toString() + ((o == null) ?
                                   "[Unlocked]" :
                                   "[Locked by thread " + o.getName() + "]");
    }
}

posted @ 2023-02-08 13:36  Cool_Yang  阅读(21)  评论(0编辑  收藏  举报