ReentrantLock解析及源码分析 (7)

ReentrantLock提供的一些其他方法 方法名称 返回值类型 方法描述
lockInterruptibly()   void   以响应中断的方式获取锁,如果在锁获取之前发生中断直接抛出中断异常,在从同步等待队列中被唤醒后检查在等待期间是否有中断发生,如果有则抛出中断异常  
tryLock()   boolean   尝试一次以非公平模式获取锁,当且仅当锁没有被获取时有可能获取成功,即便锁私用的是公平模式,直接调用 Sync的非公平模式获取一次锁,返回获取结果  
tryLock(long timeout, TimeUnit unit)   boolean   含有超时等待功能的获取锁,如果线程进入同步等待队列阻塞,则只会阻塞指定的时间,这个功能由LockSupport类提供  
newCondition()   Condition   获取一个Condition对象,可以提供类似Object Moitor一样的功能  
getHoldCount()   int   获取持有锁的次数,一般用于测试锁  
isHeldByCurrentThread   boolean   检查当前线程是否持有这个锁  
isLocked   boolean   检查锁是否被任何一个线程获取  
isFair()   boolean   检查当前锁是否是公平锁  
getOwner()   Thread   获取持有锁的线程  
hasQueuedThreads()   boolean   同步等待队列是否有线程等待获取锁  
hasQueuedThread(Thread thread)   boolean   判断指定线程是否在同步等待队列中等待  
getQueueLength()   int   获取同步等待对列的长度,队列中的线程不一定都是等待获取锁的线程,还有可能已经取消  
hasWaiters(Condition condition)   boolean   判断给定的condition中是否由线程等待  
getWaitQueueLength(Condition condition)   int   获取给定condition中等待队列的长度  
getWaitingThreads(Condition condition)   Collection<Thread>   获取给定的condition中所有的等待线程  
Condition

在ReentrantLock中提供了一个newCondition()方法,
利用返回的Condition对象可以实现Object.wait()、Object.notify()、Object.notifyAll()等功能,并且具有更强大的功能。
返回的Condition的实现是在AQS当中实现,所以这个放在AQS学习完了写。

\(\color{#FF3030}{转载请标明出处}\)

附ReentrantLock全部源码理解 /** * 一个可以重入的排他锁基本的行为和语义与使用synchronized作为 * 隐式的锁的监听器是一样的,但是实现了更多的功能 * * 一个可重入锁后被最后一次成功加锁但是没有解锁的线程持有 * 当一个锁没有被不被任何一个线程持有,这是一个线程来申请这个锁将会被申请成功 * 可以使用{@link #isHeldByCurrentThread}, 和 {@link * #getHoldCount}检查当前线程是否持有锁 * * 这个类的构造器提供了一个fairness参数来设定是否公平 * <当设置为true时,是个公平锁,锁总是被当前等待时间最长的线程获取 * 否则不能保证将按照何种顺序获取该锁 * 使用公平锁的程序吞吐量比默认(非公平锁)更小 * 但是在获得此线程和保证保证不被饿死方面会比默认更好 * 然而锁的g公平性并不保证线程的公平性。因此使用公平锁的 * 因此使用公平锁的的多个线程可能有一个会多次获得他,而其他线程可能一次也没有 * * 注意:随机的tryLock并不支持公平性, * 只要锁可用即使有其他线程正在等待也可以获取他 * * 在使用lock后使用try语句并且将unlock放在finally中 * * 除了实现{@link Lock}接口外, * 还有这个类定义了许多检查锁状态的方法。 * 其中的一些方法方法只对检测和监视有用 * * <p>Serialization of this class behaves in the same way as built-in * locks: a deserialized lock is in the unlocked state, regardless of * its state when serialized. * * <p>这个锁最多支持冲入2147483647 次(递归调用) * */ public class ReentrantLock implements Lock, java.io.Serializable { private static final long serialVersionUID = 7373984872572414699L; /** Synchronizer providing all implementation mechanics */ private final Sync sync; /** * Base of synchronization control for this lock. Subclassed * into fair and nonfair versions below. Uses AQS state to * represent the number of holds on the lock. */ abstract static class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = -5179523762034025860L; /** * Performs {@link Lock#lock}. The main reason for subclassing * is to allow fast path for nonfair version. */ abstract void lock(); /** * Performs non-fair tryLock. tryAcquire is implemented in * subclasses, but both need nonfair try for trylock method. */ 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); 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) { free = true; setExclusiveOwnerThread(null); } setState(c); return free; } protected final boolean isHeldExclusively() { // While we must in general read state before owner, // we don't need to do so to check if current thread is owner 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; } /** * Reconstitutes the instance from a stream (that is, deserializes it). */ 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; /** * 加锁. Try immediate barge, backing up to normal * acquire on failure. */ final void lock() { //使用cas操作加锁,成功的话将锁的拥有线程置为自己 if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else //排他模式获取,忽略中断,通过再次调用tryAcquire获取锁, //获取失败将进入等待队列,可能会重复的阻塞和取消阻塞, //直到调用tryAcquire获取锁成功 acquire(1); } //实现AQS的tryAcquire()方法(该方法进行一次尝试获取锁) 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); } /** * 实现AQS的tryAcquire方法,加锁时会检查当前锁的等待队列的实际元素 * 当等待队列为空(头节点==尾节点)或者头结点的下一个节点对应的线程试当前的线程可以加锁成功 * 如果当前线程已经持有 */ protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } } /** * 创建一个可重入锁.非公平模式 * 与使用 {@code ReentrantLock(false)}.创建效果一样 */ public ReentrantLock() { sync = new NonfairSync(); } /** * 创建给定模式(公平或者非公平)的可重入锁 * @param fair {@codetrue} 使用公平模式 */ public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); } /** * 获取锁. * * <p>如果这个锁没有被其他线程持有,则获取锁并立刻返回, * 将锁的计数器记为1 * * 如果当前线程已经持有锁,则将锁的计数器自增1, * 并且立刻返回 * * <p>如果锁被其他线程持有 * 那么当前线程将会因为线程调度原因设置禁用并且为休眠状态, * 并且在锁被获取之前处于休眠状态 * at which time the lock hold count is set to one. */ public void lock() { sync.lock(); } /** * 获取锁直到当前线程被阻塞 * * <p>如果锁没被其他的线程获取则获取锁并返回 * * 如果锁已经被当前线程获取,则将锁的计数器自增 * * 如果锁被其他线程持有 * 处于线程调度的目的会将当前线程设置为禁用并且为休眠状态 * 直到以下两种情况中的一种发生: * * <ul> * * <li>当前线程获取到锁; or * * <li>其他的线程中断了当前的线程 * * </ul> * * <p>如果当前线程获取到了锁,那么将锁的计数器设置为1 * * <p>如果当前线程 * * 在进入这个方法的时候中断状态已经被设置; * 或者在获取锁的过程中被中断 * * InterruptedException异常将会被抛出并且清除中断标记位 * * @throws InterruptedException if the current thread is interrupted */ public void lockInterruptibly() throws InterruptedException { //该方法会先检查当前线程是否被中断,然后调用tryAcquire获取锁 //获取失败则调用doAcquireInterruptibly //这个方法和忽略中断的加锁acquireQueue基本相同,不同点是 //当线程在调用LockSupport.park(this)被唤醒后,Lock方法会忽略是否该线程被中断, //若被中断该方法会抛出线程中断异常 sync.acquireInterruptibly(1); } /** * 当且仅当锁没被其他线程获取时才获取锁 * * <p>当且仅当锁没被其他线程获取时获取锁并且返回ture,设置锁的计数器为1 * 即使这个锁被设定为公平锁,只要没有其他线程获取到锁,使用tryLock也能立刻获取到锁 * 无论是否有其他线程在排队 * 即使这种行为破坏了公平,但在某些情况下是有用的 * 如果想要这个锁的公平设置可以使用 * {@link #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) } * 这两者几乎是的等价的 (依然会检测中断). * * 如果当前线程已经持有锁,那么将锁计数器自增加一 * * 如果当前锁被其他线程持有,那么返回false * * @return {@code true} if the lock was free and was acquired by the * current thread, or the lock was already held by the current * thread; and {@code false} otherwise */ public boolean tryLock() { //与非公平锁tryAcquire方法内容相同 return sync.nonfairTryAcquire(1); } /** * 在超时等待的时间内获取到锁并且线程没有被中断 * * 如果在超时等待的时间内获取到锁并且没有被中断,锁没有被其他线程持有 * 将返回true,同时将锁计数器设置为1 * 如果当前锁使用的是公平锁的模式 * 有其他的线程在等待这个锁,都不能获取到锁这个功能由(tryAcquire实现) * 如果想要在超时等待的时间内破坏锁的公平性获取锁可以和TryLock联合使用 * * <pre> {@code * if (lock.tryLock() || * lock.tryLock(timeout, unit)) { * ... * }}</pre> * * <p>如果当前的线程已经拥有锁那么将锁计数器自增加一(tryAcquire实现) * * <p>如果锁被其他线程持有那么处于线程调度的目的会将当前线程置为不可用 * 并且睡眠直到下面一种事情发生: * * <ul> * * <li>锁被当前线程获取,或者 * * <li>其他线程中断了当前线程 * * <li>时间超过了设置的等待时间 * * </ul> * * <p>如果获取到了锁将返回ture,并且将锁计数器设置为1 * * <p>如果当前线程 * * <ul> * * <li>在进入这个方法之前,中断标记位被设置 * * 或者获取锁的时候被中断 * * </ul> * 会抛出 {@link InterruptedException} 异常,并且清楚中断标记位 * * <p>如果超过了设置的等待时间将会返回false(其实还会尝试获取一次锁) * 如果设置的超时等待时间少于等于0,这个方法不会一直等待 * * <p>这个方法会先响应中断,而不是锁的获取和等待 * * @param timeout the time to wait for the lock * @param unit the time unit of the timeout argument * @return {@code true} if the lock was free and was acquired by the * current thread, or the lock was already held by the current * thread; and {@code false} if the waiting time elapsed before * the lock could be acquired * @throws InterruptedException if the current thread is interrupted * @throws NullPointerException if the time unit is null */ public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(timeout)); } /** * 试图释放锁 * * <p>如果当前线程是锁的持有者,则锁的计数器自减1, * 如果锁的计数器为0,则释放锁 * 如果当前线程不是锁的持有者,将抛出异常 * 释放锁成功后如果等待队列中还有等待的线程,那么调用lockSupport.unspark唤醒等待的线程 * {@link IllegalMonitorStateException}. * * @throws IllegalMonitorStateException if the current thread does not * hold this lock */ public void unlock() { sync.release(1); } /** * Returns a {@link Condition} instance for use with this * {@link Lock} instance. * * <p>The returned {@link Condition} instance supports the same * usages as do the {@link Object} monitor methods ({@link * Object#wait() wait}, {@link Object#notify notify}, and {@link * Object#notifyAll notifyAll}) when used with the built-in * monitor lock. * * <ul> * * <li>If this lock is not held when any of the {@link Condition} * {@linkplain Condition#await() waiting} or {@linkplain * Condition#signal signalling} methods are called, then an {@link * IllegalMonitorStateException} is thrown. * * <li>When the condition {@linkplain Condition#await() waiting} * methods are called the lock is released and, before they * return, the lock is reacquired and the lock hold count restored * to what it was when the method was called. * * <li>If a thread is {@linkplain Thread#interrupt interrupted} * while waiting then the wait will terminate, an {@link * InterruptedException} will be thrown, and the thread's * interrupted status will be cleared. * * <li> Waiting threads are signalled in FIFO order. * * <li>The ordering of lock reacquisition for threads returning * from waiting methods is the same as for threads initially * acquiring the lock, which is in the default case not specified, * but for <em>fair</em> locks favors those threads that have been * waiting the longest. * * </ul> * * @return the Condition object */ public Condition newCondition() { return sync.newCondition(); } /** * 查询锁被当前线程加锁的次数 * * <p>线程对于每个加锁的操作都有一个对应的解锁操作 * * <p>这个操作通常只被用来测试和调试 * For example, if a certain section of code should * not be entered with the lock already held then we can assert that * fact: * * <pre> {@code * class X { * ReentrantLock lock = new ReentrantLock(); * // ... * public void m() { * assert lock.getHoldCount() == 0; * lock.lock(); * try { * // ... method body * } finally { * lock.unlock(); * } * } * }}</pre> * * @return the number of holds on this lock by the current thread, * or zero if this lock is not held by the current thread */ public int getHoldCount() { return sync.getHoldCount(); } /** * 检查当前线程是否持有这个锁 * * <p>Analogous to the {@link Thread#holdsLock(Object)} method for * built-in monitor locks, this method is typically used for * debugging and testing. For example, a method that should only be * called while a lock is held can assert that this is the case: * * <pre> {@code * class X { * ReentrantLock lock = new ReentrantLock(); * // ... * * public void m() { * assert lock.isHeldByCurrentThread(); * // ... method body * } * }}</pre> * * <p>It can also be used to ensure that a reentrant lock is used * in a non-reentrant manner, for example: * * <pre> {@code * class X { * ReentrantLock lock = new ReentrantLock(); * // ... * * public void m() { * assert !lock.isHeldByCurrentThread(); * lock.lock(); * try { * // ... method body * } finally { * lock.unlock(); * } * } * }}</pre> * * @return {@code true} if current thread holds this lock and * {@code false} otherwise */ public boolean isHeldByCurrentThread() { return sync.isHeldExclusively(); } /** * 检查这个锁是否被任意一个线程持有(检查锁的计数器state是否是0) * 这个方法用来监控系统状态,而不是用来同步, * * @return {@code true} if any thread holds this lock and * {@code false} otherwise */ public boolean isLocked() { return sync.isLocked(); } /** * 测试当前锁是公平锁还是非公平锁 * * @return {@code true} if this lock has fairness set true */ public final boolean isFair() { return sync instanceof FairSync; } /** * 获取当前拥有锁的线程,如果没有线程持有,则返回null * 此方法的目的是为了方便构造提供更广泛的锁监视设施的子类。 * * @return the owner, or {@code null} if not owned */ protected Thread getOwner() { return sync.getOwner(); } /** * 检查是否有现成正在等待获取此锁(head!=tail) Note that * 因为线程取消获取锁可能发生在任何时间,所以返回值为true不能保证 * 一定有其他线程在获取此锁,(比如等待队列中的线程已经取消获取此锁) * 这个方法的设计被用来监控系统 * * @return {@code true} if there may be other threads waiting to * acquire the lock */ public final boolean hasQueuedThreads() { return sync.hasQueuedThreads(); } /** * 判断给定的线程是否在等待这个锁 * 线程取消获取锁可能发生在任何时间, * true的返回值不代表这个线程还在等待获取这个锁 * 这个方法的设计被用来监控系统 * * @param thread the thread * @return {@code true} if the given thread is queued waiting for this lock * @throws NullPointerException if the thread is null */ public final boolean hasQueuedThread(Thread thread) { return sync.isQueued(thread); } /** * 返回等待队列中等待获取锁的数量的估计值 * 这个方法返回的是一个估计值因为队列中的线程数量可能在变化 * 这个方法的设计被用来监控系统 * * @return the estimated number of threads waiting for this lock */ public final int getQueueLength() { return sync.getQueueLength(); } /** * 返回一个线程集合,集合中的线程可能在等待获取锁 * 因为线程获取锁可能被取消所以获取到的集合不是准确的 * 此方法的目的是为了方便构造提供更广泛的锁监视设施的子类 * * @return the collection of threads */ protected Collection<Thread> getQueuedThreads() { return sync.getQueuedThreads(); } /** * 查询与这个锁关联的condition是否有线程正在等待,即是否有现成调用过与 * await方法.因为等待超时和线程中断发生在任何时候 * 所以返回值true不代表将来会有信号来唤醒线程 * 这个方法的设计被用来监控系统 * * @param condition the condition * @return {@code true} if there are any waiting threads * @throws IllegalMonitorStateException if this lock is not held * @throws IllegalArgumentException if the given condition is * not associated with this lock * @throws NullPointerException if the condition is null */ public boolean hasWaiters(Condition condition) { if (condition == null) throw new NullPointerException(); if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject)) throw new IllegalArgumentException("not owner"); //通过检查condition队列是中的节点是否处于condition状态实现 return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition); } /** * 返回与锁相关的指定的condition的队列中的线程数量,注意这是个估计值 * 因为线程等待超时和中断发生在任何时间 * 因此队列一直在动态的变化,可能还没有统计完就已经发生了变化. * * @param condition the condition * @return the estimated number of waiting threads * @throws IllegalMonitorStateException if this lock is not held * @throws IllegalArgumentException if the given condition is * not associated with this lock * @throws NullPointerException if the condition is null */ 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); } /** * 返回与锁相关的指定的condition的队列中的线程集合 * 返回的集合只是一个估计值, * 因为线程等待超时和中断发生在任何时间 * * @param condition the condition * @return the collection of threads * @throws IllegalMonitorStateException if this lock is not held * @throws IllegalArgumentException if the given condition is * not associated with this lock * @throws NullPointerException if the condition is null */ 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() + "]"); } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyjsjx.html