package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;
import java.util.Collection;
/**
* 一种可重入互斥锁,其基本行为和语义与使用同步方法和语句访问的隐式监视器
* 锁相同,但具有扩展功能。
*
* ReentrantLock由上次成功锁定的线程拥有,但还没有解锁它。当锁不被其他线程
* 拥有时,调用锁的线程将返回并成功获取锁。如果当前线程已经拥有锁,该方法
* 将立即返回。可以使用方法#isHeldByCurrentThread和#getHoldCount来检查。
*
* 这个类的构造函数接受一个可选的公平性参数。当设置为true时,在争用状态
* 下,锁支持授予对等待时间最长的线程的访问权。否则,此锁不能保证任何特定
* 的访问顺序。使用由多个线程访问的公平锁的程序可能会显示更低的总体吞吐量
* (也就是说,更慢;通常要慢得多),但在获得锁和保证不饥饿的时间上有较小的差
* 异。但是请注意,锁的公平性并不保证线程调度的公平性。因此,许多使用公平
* 锁的线程中的一个可能在其他活动线程没有进展或当前没有持有该锁的情况下连
* 续多次获得该锁。
* 还要注意,不计时的#tryLock()方法不遵守公平性设置。如果锁是可用的,即使
* 其他线程正在等待,它也会成功。
*
* 推荐的做法是,总是在调用lock后立即使用try块,最典型的是在before/after结
* 构中,例如:
*
* <pre> {@code
* class X {
* private final ReentrantLock lock = new ReentrantLock();
* // ...
*
* public void m() {
* lock.lock(); // 阻塞直到条件保持
* try {
* // ... method body
* } finally {
* lock.unlock()
* }
* }
* }}</pre>
*
* 除了实现Lock接口之外,该类还定义了许多用于检查锁状态的公共方法和受保护
* 方法。其中一些方法只对检测和监视有用。
*
* 该类的序列化行为与内置锁的行为相同:反序列化的锁处于解锁状态,而与序列化
* 时的状态无关。
*
* 这个锁最多支持同一个线程的2147483647个递归锁。尝试超过此限制将导致锁定
* 方法抛出错误。(20亿)
*
* @since 1.5
* @author Doug Lea
*/
public class ReentrantLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = 7373984872572414699L;
/** 提供所有实现机制的同步器 */
private final Sync sync;
/**
* 这个锁的同步控制基础。子类分为以下的公平和不公平版本。使用AQS的
* state属性来表示锁上的持有数。
*/
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
/**
* 执行锁#锁。子类化(抽象化?)的主要原因是允许非公平版本的快速路
* 径。
*/
abstract void lock();
/**
* 执行不公平锁的tryLock。tryAcquire在子类中实现,但都需要trylock
* 方法的不公平尝试。
*/
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() {
// 虽然我们通常必须在所有者之前读取状态,但我们不需要
// 检查当前线程是否为所有者
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
}
}
/**
* Sync object for non-fair locks
* 非公平锁的同步对象
*/
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
/**
* 执行锁。尝试立即抢锁,失败的话,执行正常的acquire方法。
*/
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
/**
* Sync object for fair locks
* 公平锁同步对象
*/
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
acquire(1);
}
/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/
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;
}
}
/**
* Creates an instance of {@code ReentrantLock}.
* This is equivalent to using {@code ReentrantLock(false)}.
*/
public ReentrantLock() {
sync = new NonfairSync();
}
/**
* Creates an instance of {@code ReentrantLock} with the
* given fairness policy.
*
* @param fair {@code true} if this lock should use a fair ordering policy
*/
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
/**
* 获得锁
*
* 如果锁没有被其他线程持有,则获取锁并返回
* 立即将state设置为1。
*
* 如果当前线程已经持有锁,那么持有计数将增加1,该方法将立即返回。
*
* <p>如果锁被另一个线程持有,那么当前线程出于线程调度目的将被禁用,并
* 处于休眠状态,直到获得锁,此时锁持有计数被设置为1。
*/
public void lock() {
sync.lock();
}
/**
* 如果锁被另一个线程持有,那么当前线程将被禁用,除非当前线程获得了锁
* {@linkplain Thread#interrupt interrupted}.
*
* 如果锁没有被其他线程持有,则获取锁并返回
* 立即将锁保持数设置为1。
*
* 如果当前线程已经持有该锁,则保持计数
* 加1,方法立即返回。
*
* <p>如果锁被另一个线程持有,那么当前线程就会因为线程调度的目的而被禁
* 用,并处于休眠状态,直到有以下两种情况发生:
*
* <ul>
*
* <li>锁是由当前线程获取的;或
*
* <li>当前线程是Thread中的中断线程
*
* </ul>
*
* <p>如果当前线程获得了锁,那么锁将保持不变
* count设置为1。
*
* <p>如果当前线程:
*
* <ul>
*
* <li>在进入该方法时设置中断状态;或
*
* <li>是Thread中的中断线程获得了锁
*
* </ul>
*
* 那就抛出InterruptedException,并清除当前线程的中断状态。
*
* <p>在这个实现中,因为这个方法是一个显式的中断点,所以优先考虑响应中
* 断,而不是正常的或重入的锁获取。
*
* 如果当前线程被中断,则抛出InterruptedException
*/
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
/**
* 只有在调用时锁没有被另一个线程持有时才获取该锁。
*
* 如果锁没有被其他线程持有,则获取该锁,并立即返回值为true,将锁持有
* 计数设置为1。即使该锁被设置为使用公平排序策略,如果锁可用,对
* tryLock()的调用将立即获得该锁,无论其他线程当前是否正在等待该锁。这
* 种“干扰”行为在某些情况下是有用的,即使它破坏了公平。如果您想尊重这
* 个锁的公平性设置,那么使用#tryLock(long, TimeUnit) tryLock(0,
* TimeUnit.SECONDS),这几乎是等价的(它也检测中断)。
*
* <p>如果当前线程已经持有该锁,则持有计数增加1,该方法返回true。
*
* <p>如果锁被另一个线程持有,那么这个方法将立即返回,值为false。
*
* 如果锁是空闲的并且被当前线程获取,或者锁已经被当前线程持有,则返回
* true;否则,则返回false
*/
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
/**
* 如果在给定的等待时间内没有被其他线程持有,并且当前线程没有被
* Thread#interrupt中断,则获取该锁。
*
* <p>如果锁没有被其他线程持有,则获取该锁,并立即返回值为true,将锁持
* 有计数设置为1。如果该锁被设置为使用公平排序策略,那么如果有其他线程
* 正在等待该锁,则不会获得可用的锁。这与#tryLock()方法相反。如果你想
* 要一个定时的tryLock(),它允许在一个公平的锁上进行操作,那么将定时和
* 非定时的形式组合在一起:
*
* <pre> {@code
* if (lock.tryLock() ||
* lock.tryLock(timeout, unit)) {
* ...
* }}</pre>
*
* 如果当前线程已经持有该锁,则持有计数增加1,该方法返回true。
*
* 如果锁被另一个线程持有,那么当前线程就会因为线程调度的目的而被禁
* 用,并处于休眠状态,直到以下三种情况之一发生:
*
* <ul>
*
* <li>锁是由当前线程获取的;或
*
* <li>当前线程被Thread中的interrupt打断,或
*
* <li>超过指定的等待时间
*
* </ul>
*
* <p>如果获得了锁,则返回值true,并将锁保持计数设置为1。
*
* <p>如果当前线程:
*
* <ul>
*
* <li>在进入该方法时已经被设置为中断状态;或
*
* <li>当获取锁时,已经被Thread.interrupt()打断
*
* </ul>
* 就会抛出InterruptedException,并清除当前线程的中断状态。
*
* <p>如果指定的等待时间过去了,则返回值false。如果时间小于或等于零,
* 该方法将根本不等待。
*
* <p>在这个实现中,由于这个方法是一个显式的中断点,所以优先考虑响应中
* 断,而不是正常或重入获取锁,也不是报告等待时间的推移。
*
* @param timeout 等待锁定的时间
* @param unit 参数的时间单位
* @return {@code true} 如果锁是空闲的,并且被当前线程获得,或者该锁
* 已经被当前线程持有;
* and {@code false} 如果在获得锁之前的等待时间已经过去,则为false
* @throws InterruptedException if the current thread is interrupted
* @throws NullPointerException 如果时间单位为空 */
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
/**
* 尝试释放此锁。
* <p>I如果当前线程是该锁的持有者,则保持计数减少。如果保持计数现在为
* 零,那么锁将被释放。如果当前线程不是该锁的持有者,则会抛出非法的监
* 视器状态异常。
*
* @throws IllegalMonitorStateException 如果当前线程没有持有此锁
*/
public void unlock() {
sync.release(1);
}
/**
* 返回与此锁实例一起使用的Condition实例。
*
* <p>返回的Condition实例与对象监视器方法({Object#wait() wait},
* {Object#notify notify}, and {Object#notifyAll notifyAll})在内置
* 监视器锁上使用时的用法相同。
*
* <ul>
*
* <li>如果在调用{Condition} {Condition#await() waiting}或
* {Condition#signal signaling}方法时没有持有该锁,则抛出
* {IllegalMonitorStateException}。
*
* <li>当condition {condition #await() await}方法被调用时,锁被释放,
* 在它们返回之前,锁被重新获取,锁保持计数恢复到方法被调用时的值。
*
* <li>如果是{thread #interrupt interrupted}线程在等待,那
* 么等待将终止,一个{InterruptedException}将被抛出,线程的中断状态将
* 被清除。
*
* <li> 等待线程以先进先出顺序发出信号。
*
* <li>从等待方法返回的线程重新获取锁的顺序与最初获取锁的线程相同,这
* 在默认情况下没有指定,但对于公平锁,优先于等待时间最长的线程。
*
* </ul>
*
* @return the Condition object
*/
public Condition newCondition() {
return sync.newCondition();
}
/**
* 查询当前线程对该锁的持有数。
*
* <p>一个线程对每一个锁操作持有一个锁,而这个锁操作与解锁操作不匹配。 *
* <p>保持计数信息通常只用于测试和调试目的。例如,如果某段代码不应该在
* 已经持有锁的情况下输入,那么我们可以断言:
*
* <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 当前线程持有该锁的数量,如果当前线程没有持有该锁,则为0
*/
public int getHoldCount() {
return sync.getHoldCount();
}
/**
* 查询当前线程是否持有该锁。
*
* <p>与内置监视器锁的{Thread#holdsLock(Object)}方法类似,这个方法通
* 常用于调试和测试。例如,只有在锁被持有时才应该调用的方法可以断言是
* 这样的:
*
* <pre> {@code
* class X {
* ReentrantLock lock = new ReentrantLock();
* // ...
*
* public void m() {
* assert lock.isHeldByCurrentThread();
* // ... method body
* }
* }}</pre>
*
* <p>它也可以用来确保重入锁以没有重入时才能使用,例如:
*
* <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} 如果当前线程持有此锁
* {@code false} 否则
*/
public boolean isHeldByCurrentThread() {
return sync.isHeldExclusively();
}
/**
* 查询该锁是否被任何线程持有。此方法设计用于监控系统状态,而不是用于
* 同步控制。
*
* @return {@code true} if any thread holds this lock and
* {@code false} otherwise
*/
public boolean isLocked() {
return sync.isLocked();
}
/**
* Returns {@code true} if this lock has fairness set true.
*
* @return {@code true} if this lock has fairness set true
*/
public final boolean isFair() {
return sync instanceof FairSync;
}
/**
* 返回当前拥有该锁的线程,如果没有,则返回{@code null}。当不是所有者
* 的线程调用此方法时,返回值反映了当前锁状态的最佳近似值。例如,即使
* 有线程试图获得锁,但还没有这样做,该锁的所有者也可能暂时是{@code
* null}。这种方法的设计是为了方便构造提供更广泛的锁监控设施的子类。
*
* @return the owner, or {@code null} if not owned
*/
protected Thread getOwner() {
return sync.getOwner();
}
/**
*查询是否有线程正在等待获取该锁。请注意,因为取消可能在任何时候发生
返回{@code true}并不保证任何其他线程会获得这个锁。该方法主要用于监控
系统状态。
*
* @return {@code true} if there may be other threads waiting to
* acquire the lock
*/
public final boolean hasQueuedThreads() {
return sync.hasQueuedThreads();
}
/**
* 查询给定线程是否正在等待获取该锁。注意,因为取消可能在任何时候发
* 生,返回{@code 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。请注意,由于超时和中断
* 可能在任何时候发生,{@code true}返回不能保证将来的{@code信号}将唤
* 醒任何线程。该方法主要用于监控系统状态。
*
* @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");
return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)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);
}
/**
* 返回一个集合,其中包含可能正在等待与此锁关联的给定条件的线程。因为
* 在构造这个结果时,实际的线程集可能会动态地改变,所以返回的集合只是
* 最好的估计结果。返回集合的元素没有特定的顺序。这种方法的设计是为了
* 便于构造提供更广泛的状态监测设施的子类。
*
* @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);
}
/**
* 返回标识此锁及其锁状态的字符串。括号中的状态包括字符串{@code
* "Unlocked"}或字符串{@code "Locked by"},后跟所属线程的{@linkplain
* Thread#getName name}。
*
* @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() + "]");
}
}