https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantLock.html
ReentrantLock
java.util.concurrent.locks.ReentrantLock
public class ReentrantLock extends Object implements Lock, Serializable
一种可重入互斥锁,其基本行为和语义与使用同步方法和语句访问的隐式监视器锁相同,但具有扩展功能。
ReentrantLock 由上次成功锁定但尚未解锁的线程拥有。当锁不被另一个线程拥有时,调用锁的线程将返回,成功获取锁。如果当前线程已经拥有锁,该方法将立即返回。这可以使用方法 isHeldByCurrentThread() 和 getHoldCount() 来检查。
此类的构造函数接受一个可选的公平参数。当设置为 true 时,在争用情况下,锁有利于授予对等待时间最长的线程的访问权限。否则,此锁不保证任何特定的访问顺序。使用由许多线程访问的公平锁的程序可能会显示出比使用默认设置的程序更低的整体吞吐量(即,更慢;通常要慢得多),但在获取锁和保证不会出现饥饿的情况下具有较小的时间差异。但是请注意,锁的公平性并不能保证线程调度的公平性。因此,使用公平锁的许多线程之一可能会连续多次获得它,而其他活动线程没有进展并且当前没有持有锁。另请注意,不定时的 tryLock 方法不遵守公平设置。如果锁可用,即使其他线程正在等待,它也会成功。
推荐的做法是总是在调用 lock 之后立即使用 try 块,最常见的是在构造之前/之后,例如:
class X {
private final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
}
除了实现 Lock 接口之外,该类还定义了方法 isLocked 和 getLockQueueLength,以及一些可能对检测和监控有用的相关受保护访问方法。
此类的序列化与内置锁的行为方式相同:反序列化锁处于未锁定状态,无论其在序列化时的状态如何。
此锁最多支持同一线程的 2147483647 个递归锁。 尝试超过此限制会导致锁定方法抛出错误。
Method Detail
public void lock()
获取锁。
如果没有被另一个线程持有,则获取锁并立即返回,将锁持有计数设置为 1。
如果当前线程已经持有锁,则持有计数加一并且该方法立即返回。
如果锁被另一个线程持有,那么当前线程将被禁用以用于线程调度目的并处于休眠状态,直到获得锁为止,此时锁持有计数设置为 1。
public boolean tryLock()
仅当调用时没有被另一个线程持有时才获取锁。
如果锁没有被另一个线程持有,则获取锁并立即返回值为 true,将锁持有计数设置为 1。 即使此锁已设置为使用公平排序策略,调用 tryLock() 也会立即获取该锁(如果可用),无论其他线程当前是否正在等待该锁。 这种“闯入”行为在某些情况下可能很有用,即使它破坏了公平性。 如果您想尊重此锁的公平设置,请使用几乎等效的 tryLock(0, TimeUnit.SECONDS) (它也检测中断)。
如果当前线程已经持有这个锁,那么持有计数加一并且该方法返回真。
如果锁被另一个线程持有,则此方法将立即返回值为 false。
public Condition newCondition()
返回与此 Lock 实例一起使用的 Condition 实例。
返回的 Condition 实例在与内置监视器锁一起使用时支持与对象监视器方法(wait、notify 和 notifyAll)相同的用法。
如果在调用任何 Condition 等待或信号方法时未持有此锁,则会引发 IllegalMonitorStateException。
当条件等待方法被调用时,锁被释放,在它们返回之前,锁被重新获得,锁持有计数恢复到调用方法时的状态。
如果线程在等待过程中被中断,则等待将终止,将抛出 InterruptedException,并清除线程的中断状态。
等待线程以 FIFO 顺序发出信号。
从等待方法返回的线程重新获取锁的顺序与最初获取锁的线程相同,在默认情况下未指定,但对于公平锁,优先考虑那些等待时间最长的线程。
public int getHoldCount()
查询当前线程持有该锁的次数。
对于解锁操作不匹配的每个锁定操作,线程都持有一个锁。
保持计数信息通常仅用于测试和调试目的。 例如,如果某段代码不应该在已经持有锁的情况下输入,那么我们可以断言这个事实:
class X {
ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
assert lock.getHoldCount() == 0;
lock.lock();
try {
// ... method body
} finally {
lock.unlock();
}
}
}
public boolean isHeldByCurrentThread()
查询当前线程是否持有该锁。
类似于内置监视器锁的 Thread.holdsLock(java.lang.Object) 方法,此方法通常用于调试和测试。 例如,一个只应在持有锁时调用的方法可以断言是这种情况:
class X {
ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
assert lock.isHeldByCurrentThread();
// ... method body
}
}
It can also be used to ensure that a reentrant lock is used in a non-reentrant manner, for example:
class X {
ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
assert !lock.isHeldByCurrentThread();
lock.lock();
try {
// ... method body
} finally {
lock.unlock();
}
}
}
protected Thread getOwner()
返回当前拥有此锁的线程,如果不拥有,则返回 null。 当不是所有者的线程调用此方法时,返回值反映了当前锁定状态的最大努力近似值。 例如,即使有线程试图获取锁但尚未这样做,所有者也可能暂时为空。 此方法旨在促进提供更广泛的锁监视设施的子类的构建。
网友评论