Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

被面试官吊打系列之 ReentrantLock 源码级别 逐字逐句 吐血详尽分析

CanntBelieve 2020-04-07 13:36:00 阅读数:60 评论数:0 点赞数:0 收藏数:0

ReentrantLock 内部有一个基于AQS的Sync,然后 衍生了 NonfairSync FairSync ... 每次只获取、释放 一个资源;

主要需要理解两个关键点: 可重入锁 、 公平锁和非公平锁

 可重入的意思是线程在执行 lock 方法包围起来的临界区的内部代码,还可以调用lock。其实在java 中,synchronized和java.util.concurrent.locks.ReentrantLock都是可重入锁!!!

 

广义上的可重入锁指的是可重复可递归调用的锁,在外层使用锁之后,在内层仍然可以使用,并且不发生死锁(前提得是同一个对象或者class),这样的锁就叫做可重入锁。ReentrantLock和synchronized都是可重入锁; 不可重入锁,与可重入锁相反,不可递归调用,递归调用就发生死锁。看到一个经典的讲解,使用自旋锁来模拟一个不可重入锁

参考:https://blog.csdn.net/u013452335/article/details/86576939     https://blog.csdn.net/rickiyeat/article/details/78314451 

 

 公平性的讨论在下面有提及:

 

/*
重入式的相互排斥{@链接锁},基本相同的
的行为和语义,与使用
{@code synchronized}方法和语句,但带有扩展的
能力。
<p>一个{@code ReentrantLock}是<em>拥有</em>的线程</em>。
成功锁定,但还没有解锁。调用的线程
{@code lock}将返回,成功获取锁,当
锁不属于其他线程。该方法将返回
如果当前线程已经拥有了锁,那么就会立即使用。这种情况下,可以
使用方法{@link #isHeldByCurrentThread}和{@link
#getHoldCount}。
<p>这个类的构造函数接受一个可选的
<em>公平性</em>参数。 当设置{@code true}时,在
争论的是,锁具有利于让等待时间最长的人进入。
线程。 否则,此锁并不能保证任何特定的
访问顺序。 使用由多个线程访问的公平锁的程序
可能显示出较低的总体吞吐量(即速度较慢;通常要慢得多。
比那些使用默认设置的人更慢),但比使用默认设置的人的速度更慢。
差异化的时间来获取锁具和保证不被锁住
饿死了。但请注意,锁定的公平性并不能保证
线程调度的公平性。因此,许多线程中的一个使用
公道的锁,可以连续多次获得,而其他
活动中的线程没有进展,目前不持有
锁定。
另外要注意的是,不定时的{@link #tryLock()}方法并没有
尊重公平性设置。它将成功,如果锁定
即使其他线程在等待,也是可用的。
<p>推荐的做法是:<em>总是</em>立即</em>。
在调用{@code lock}后,使用{@code try}块,大部分的
通常是在前后结构中,例如。
<pre> {@code
X类 {
private final ReentrantLock Lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); ///阻塞,直到条件成立为止。
试试
///...方法正文
} 最后 {
解锁()
}
}
}}</pre>
<p>除了实现{@link Lock}接口外,这个
类定义了一些{@code public}和{@code protected}。
检查锁的状态的方法。 其中有些方法是:
方法只对仪表和监控有用。
<p>该类的序列化行为与内置的方法相同。
锁:反序列化的锁是处于未锁状态,无论
其序列化时的状态。
<p>此锁最多支持2147483647个递归锁,通过
同一条线程。试图超过这一限制的结果是
{@link Error}从锁定方法抛出。
的行为和语义,就像隐式监控锁一样,使用
{@code synchronized}方法和语句,但带有扩展的
能力。
可重入的独占锁 同隐含 监视器锁 拥有相同的基本行为和语义
<p>一个{@code ReentrantLock}是<em>拥有</em>的线程</em>,由最后一个
成功锁定,但还没有解锁。调用的线程
{@code lock}将返回,成功获取锁,当
锁不属于其他线程。该方法将返回
如果当前线程已经拥有了锁,那么就会立即使用。这种情况下,可以
使用方法{@link #isHeldByCurrentThread}和{@link
#getHoldCount}。
<p>这个类的构造函数接受一个可选的
<em>公平性</em>参数。 当设置{@code true}时,在
争论的是,锁具有利于让等待时间最长的人进入。
线程。 否则,此锁并不能保证任何特定的
访问顺序。 使用由多个线程访问的公平锁的程序
可能显示出较低的总体吞吐量(即速度较慢;通常要慢得多。
比那些使用默认设置的人更慢),但比使用默认设置的人的速度更慢。
差异化的时间来获取锁具和保证不被锁住
饿死了。但请注意,锁定的公平性并不能保证
线程调度的公平性。因此,许多线程中的一个使用
公道的锁,可以连续多次获得,而其他
活动中的线程没有进展,目前不持有
锁定。
另外要注意的是,不定时的{@link #tryLock()}方法并没有
尊重公平性设置。它将成功,如果锁定
即使其他线程在等待,也是可用的。
<p>推荐的做法是:<em>总是</em>立即</em>。
在调用{@code lock}后,使用{@code try}块,大部分的
通常是在前后结构中,例如。
<pre> {@code
X类 {
private final ReentrantLock Lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); ///阻塞,直到条件成立为止。
试试
///...方法正文
} 最后 {
解锁()
}
}
}}</pre>
<p>除了实现{@link Lock}接口外,这个
类定义了一些{@code public}和{@code protected}。
检查锁的状态的方法。 其中有些方法是:
方法只对仪表和监控有用。
<p>该类的序列化行为与内置的方法相同。
锁:反序列化的锁是处于未锁状态,无论
其时的状态
<P>此锁最多支持2147483647次递归锁,通过
同一条线程。试图超过这一限制的结果是
{@link Error}从锁定方法中抛出。
通过www.DeepL.com/Translator(免费版)翻译
公平锁,意味着无用的唤醒会比较少,但是相对非公平锁,效率会有所下降!
@since 1.5
@author Doug Lea
/
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.
该锁的同步控制基础。子类分为下面的公平和非公平版本。使用AQS状态来代表锁上的持有数量。
/
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.
执行{@link Lock#lock}。子类化的主要原因是为了让非公平版的快速通道。
/
abstract void lock();
/**
Performs non-fair tryLock. tryAcquire is implemented in
subclasses, but both need nonfair try for trylock method.
执行非公平的tryLock。 tryAcquire由子类实现,但都需要非公平的trylock方法。
/
可以看到此方法仅仅是做一个快速的尝试,成功则;不会等待。
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) { 还未被占用,AQS还未初始化
if (compareAndSetState(0, acquires)) { cas设置资源量,以免突然之间又进来一个线程
setExclusiveOwnerThread(current); 设置线程拥有者,setExclusiveOwnerThread是AQS的父类AbstractOwnableSynchronizer接口定义的方法,
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; 返回true
}
return false; 表示快速方式 获取失败。
}
protected final boolean tryRelease(int releases) { 注意是protected方法,可以被子类复写
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread()) 如果当前线程不是同步器owner,那么是非法状态,抛异常
throw new IllegalMonitorStateException();
boolean free = false; 默认是失败
if (c == 0) {
free = true; 只有完全释放了,才算tryRelease成功
setExclusiveOwnerThread(null); 完全释放了,同时同步器owner 为空,表示其他线程可以进入
}
setState(c); 不管是否完全释放, 都释放一定的资源量,
return free;
}
是否被当前线程 独占了同步器
protected final boolean isHeldExclusively() { 实现了AQS的isHeldExclusively方法
// While we must in general read state before owner,
// we don't need to do so to check if current thread is owner
虽然一般来说,我们必须先看状态,再看拥有者。 我们不需要这样做,以检查当前的线程是否是所有者。why?大概因为它只会在条件对象中被调用,而条件对象是只适用于独占模式的,所以同步器 只能被一个线程占用。
return getExclusiveOwnerThread() == Thread.currentThread();
}
final ConditionObject newCondition() {
return new ConditionObject();
}
// Methods relayed from outer class 从外部类转发过来的方法; outer class 是指Enclosing 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
}
}
/**
Sync object for non-fair locks 非公平版本
/
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
/**
Performs lock. Try immediate barge, backing up to normal
acquire on failure.
锁定同步器,也就是给同步器上锁,让其他线程无法进入
先尝试立即的闯入,(在没有竞争的时候,这个很简单有效),闯入失败则退回到acquire
/
final void lock() {
if (compareAndSetState(0, 1)) // 先简单的尝试获取1个资源, 不管是否有线程在等待
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1); // 这个方法其实会调用下面的tryAcquire,然后是调用nonfairTryAcquire
注意 这里需要的资源是1
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires); 非公平的方式实现AQS的tryAcquire方法
}
}
/**
Sync object for fair locks 公平锁的同步对象
/
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
acquire(1); 注意 这里需要的资源是1; 这个方法其实会调用下面的tryAcquire
}
/**
Fair version of tryAcquire. Don't grant access unless
recursive call or no waiters or is first.
公平版的tryAcquire。 除非是递归调用或没有服务员或者是第一个,否则不要授予访问权限。
/
其实两个版本的 tryAcquire 区别在于c == 0时候的处理。
公平锁需要保证同步队列的head就是当前线程或者 目前为空; —— 这样; 差别几乎就是一个hasQueuedPredecessors,后面其实都一样,都是简单的判断是否被独占,然后..
公平就是说,你新过来的线程需要先排队,当然,如果队列为空,那么自然不要排队; 其实我感觉只需要检查一下队列是否为空即可,不为空则表示已有竞争,state肯定不为0,然后就滚去排队;
有一种情况是,队列确实不为空,比如两个节点:head-tail,但是此时tail 刚刚被取消了,那么...
非公平就是说,你新过来的线程不需要先排队,而是直接和老二竞争,当然,如果队列为空,那么自然不要排队,也没有竞争的问题
hasQueuedPredecessors 是一个特别的方法: c == 0的情况下,同步队列仍然可能存在 节点?仍需要判断前面是否已有节点入队? 这个可能是对应一种极端的情况,就是 刚刚比较完, 后面突然立马进来了几个线程.. 或者就是head已经(由于中断、超时等原因)释放,state被设置为0,但node未来得及出队..
更新: !hasQueuedPredecessors 其实就是判断是否队列为空或者当前是head或head.next;就是说,是第二个,那么是有资格进行立即获取的,那么并不违反公平性。
更新: !hasQueuedPredecessors 其实就是判断是否 没有竞争 或者 队列为空但已经有一个其他的线程正在执行;
AQS的acquire方法中,首次执行tryAcquire的时候,线程可能还未入队,这样做的原因是,如果没有竞争,那就不用初始化队列了!是一个快速的方式!
其实acquireQueued方法中,每次被唤醒都会先判断前任是不是head,然后再调用tryAcquire。就是说对于非公平锁,还是需要排队的! 和公平锁的差别,基本上是非常非常的细微,———— 所谓不公平,几乎仅仅就是 首次执行acquire的时候 不公平 !!
总结
非公平锁和公平锁的两处不同 (记住, 就是两点区别):
1 非公平锁在调用 lock 后,首先就会调用 CAS 进行一次抢锁,如果这个时候恰巧锁没有被占用,那么直接就获取到锁返回了。
2 非公平锁在 CAS 失败后,和公平锁一样都会进入到 tryAcquire 方法,在 tryAcquire 方法中,如果发现锁这个时候被释放了(state == 0),非公平锁会直接 CAS 抢锁,但是公平锁会判断等待队列是否有线程处于等待状态,如果有则不去抢锁,乖乖排到后面。
公平锁和非公平锁就这两点区别,如果这两次 CAS 都不成功,那么后面非公平锁和公平锁是一样的,都要进入到阻塞队列等待唤醒。
相对来说,非公平锁会有更好的性能,因为它的吞吐量比较大。当然,非公平锁让获取锁的时间变得更加不确定,可能会导致在阻塞队列中的线程长期处于饥饿状态, 因为它可能导致了某些线程 需要等待更久,造成饥饿!。
为什么 非公平锁会有更好的性能,因为它的吞吐量比较大 ? 这个其实要看一下锁的释放:
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
可以看到,如果线程L1 执行tryRelease成功了,那么state 应该就是0,但是此时非公平锁L3进来了开始lock(), 而release方法内部的unparkSuccessor 还未执行,head的next(假设是L2) 还未唤醒(因为可能还未执行到那一行); 这样L3 不用阻塞,L2 也可能不用唤醒,当然,也可能L2 可能被唤醒,但是又被阻塞..
因为它可以使总体的 park unpark 时间更少,减少总体的阻塞时间,虽然造成了一些不公平,但是它确实
作者:小北觅
链接:https://www.jianshu.com/p/2ada27eee90b
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) { 还未有其他线程占用同步器, 比如 还没有竞争、或刚好释放了
if (!hasQueuedPredecessors() && 没有已经入队的前任
compareAndSetState(0, acquires)) { cas成功
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;
}
其实这里应该还有个else, 就是c>0且当前线程不是同步器所有者,那么其实也是 false
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();
}
/**
Acquires the lock.
<p>Acquires the lock if it is not held by another thread and returns
immediately, setting the lock hold count to one.
<p>If the current thread already holds the lock then the hold
count is incremented by one and the method returns immediately.
<p>If the lock is held by another thread then the
current thread becomes disabled for thread scheduling
purposes and lies dormant until the lock has been acquired,
at which time the lock hold count is set to one.
<p>如果锁没有被其他线程持有,则获取锁并返回
立即,将锁的保持数设置为1。
<p>如果当前线程已经持有锁,那么保持数
数值递增1,并立即返回该方法。
<p>如果锁被其他线程持有,那么
当前线程将被禁用,无法进行线程调度
目的,并在获得锁之前处于休眠状态。
这时,锁住次数被设置为1。
dormant 蛰伏, 其实就是阻塞。
获取同步锁。 如果
/
public void lock() {
sync.lock();
}
/**
Acquires the lock unless the current thread is
{@linkplain Thread#interrupt interrupted}.
<p>Acquires the lock if it is not held by another thread and returns
immediately, setting the lock hold count to one.
<p>If the current thread already holds this lock then the hold count
is incremented by one and the method returns immediately.
<p>If the lock is held by another thread then the
current thread becomes disabled for thread scheduling
purposes and lies dormant until one of two things happens:
<ul>
<li>The lock is acquired by the current thread; or
<li>Some other thread {@linkplain Thread#interrupt interrupts} the
current thread.
</ul>
<p>If the lock is acquired by the current thread then the lock hold
count is set to one.
<p>If the current thread:
<ul>
<li>has its interrupted status set on entry to this method; or
<li>is {@linkplain Thread#interrupt interrupted} while acquiring
the lock,
</ul>
then {@link InterruptedException} is thrown and the current thread's
interrupted status is cleared.
<p>In this implementation, as this method is an explicit
interruption point, preference is given to responding to the
interrupt over normal or reentrant acquisition of the lock.
获得锁,除非当前线程是
{@linkplain Thread#interrupt interrupted}。
<p>如果锁没有被其他线程持有,则获取该锁并返回
立即,将锁的保持数设置为1。
<p>如果当前线程已经持有此锁,那么保持数
增量为1,并且该方法立即返回。
<p>如果锁被其他线程持有,那么
当前线程被禁用,无法进行线程调度
目的,并处于休眠状态,直到发生两种情况之一。
<ul>
<li>该锁由当前线程获得;或
<li>其他线程{@linkplain线程#中断中断}。
目前的线程。
</ul
<p>如果锁是由当前线程获得的,那么锁保持
count被设置为1。
<p>如果当前线程。
<ul
<li>在进入此方法时,其中断状态已被设置为中断状态;或
<li>是{@linkplain线程#中断中断}吗? 的锁。
</ul>
然后 {@link InterruptedException}会被抛出,并且当前线程的
中断的状态被清除。
<p>在本实施例中,由于该方法是一个显式的
中断点,优先考虑回应
中断超过正常或重入式获取锁。
通过www.DeepL.com/Translator(免费版)翻译
@throws InterruptedException if the current thread is interrupted
/
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
/**
Acquires the lock only if it is not held by another thread at the time
of invocation.
<p>Acquires the lock if it is not held by another thread and
returns immediately with the value {@code true}, setting the
lock hold count to one. Even when this lock has been set to use a
fair ordering policy, a call to {@code tryLock()} <em>will</em>
immediately acquire the lock if it is available, whether or not
other threads are currently waiting for the lock.
This &quot;barging&quot; behavior can be useful in certain
circumstances, even though it breaks fairness. If you want to honor
the fairness setting for this lock, then use
{@link #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
which is almost equivalent (it also detects interruption).
<p>If the current thread already holds this lock then the hold
count is incremented by one and the method returns {@code true}.
<p>If the lock is held by another thread then this method will return
immediately with the value {@code 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
/
只有在当时没有被其他线程持有的情况下,才会获得锁 的调用。
<p>如果锁不是由另一个线程持有,那么就会获取该锁。
立即返回值{@code true},设置为
锁定保持数为1。即使该锁已被设置为使用一个
公平订购策略,调用{@code tryLock()} <em>将</em></em>
如果有锁,则立即购买,无论是否有锁
其他线程目前正在等待锁定。
这种&quot;barging&quot;行为在某些情况下是有用的。
情况下,即使打破了公平。如果你想尊重
此锁的公平性设置,然后使用
{@link #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
几乎是等效的(它也会检测到中断)。
<p>如果当前的线程已经持有这个锁,那么持有的
count被递增1,并且该方法将返回{@code true}。
<p>如果锁被另一个线程持有,那么这个方法将返回{@code true}。
值 {@code false}立即返回 {@code false}。
如果该锁是自由的,并且是通过
锁定,或者当前线程已经被当前的
线程; 和 {@code false}否则
public boolean tryLock() { 浅尝而止 浅尝辄止
return sync.nonfairTryAcquire(1);
}
/**
Acquires the lock if it is not held by another thread within the given
waiting time and the current thread has not been
{@linkplain Thread#interrupt interrupted}.
<p>Acquires the lock if it is not held by another thread and returns
immediately with the value {@code true}, setting the lock hold count
to one. If this lock has been set to use a fair ordering policy then
an available lock <em>will not</em> be acquired if any other threads
are waiting for the lock. This is in contrast to the {@link #tryLock()}
method. If you want a timed {@code tryLock} that does permit barging on
a fair lock then combine the timed and un-timed forms together:
<pre> {@code
if (lock.tryLock() ||
lock.tryLock(timeout, unit)) {
...
}}</pre>
<p>If the current thread
already holds this lock then the hold count is incremented by one and
the method returns {@code true}.
<p>If the lock is held by another thread then the
current thread becomes disabled for thread scheduling
purposes and lies dormant until one of three things happens:
<ul>
<li>The lock is acquired by the current thread; or
<li>Some other thread {@linkplain Thread#interrupt interrupts}
the current thread; or
<li>The specified waiting time elapses
</ul>
<p>If the lock is acquired then the value {@code true} is returned and
the lock hold count is set to one.
<p>If the current thread:
<ul>
<li>has its interrupted status set on entry to this method; or
<li>is {@linkplain Thread#interrupt interrupted} while
acquiring the lock,
</ul>
then {@link InterruptedException} is thrown and the current thread's
interrupted status is cleared.
<p>If the specified waiting time elapses then the value {@code false}
is returned. If the time is less than or equal to zero, the method
will not wait at all.
<p>In this implementation, as this method is an explicit
interruption point, preference is given to responding to the
interrupt over normal or reentrant acquisition of the lock, and
over reporting the elapse of the waiting time.
@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));
}
/**
Attempts to release this lock.
<p>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.
如果当前的线程是该锁的持有者,那么该锁的持有者就会被持有
数被递减。 如果现在的保持数为零,那么锁的数量就会减少。
被释放。 如果当前线程的持有人不是这个
锁,然后{@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>
返回一个{@link条件}实例,用于与这个
{@link Lock}实例。
<p>返回的{@link条件}实例支持相同的
使用方法({@link对象}监控方法({@link
Object#wait() wait}, {@link Object#notify notify notify}, 和 {@link
Object#notifyAll notifyAll})与内置的
监视器锁。
<ul>。
<li>如果当{@link条件}中的任何一项没有被锁定时,该锁没有被保持。
{@linkplain Condition#await() waiting}或{@linkplain
Condition#signal signalling}方法被调用,那么{@link
IllegalMonitorStateException}被抛出。
<li>当条件{@linkplain Condition#await() 等待}时
的方法被调用,并且在它们之前,锁被释放,而在它们
返回时,锁被重新获得,并恢复锁的持有次数。
到方法被调用时的状态。
<li>如果一个线程是{@linkplain Thread#interrupt中断}。
在等待时,等待将终止,{@link
InterruptedException}将被抛出,而线程的
中断的状态将被清除。
<li>等待的线程按FIFO顺序发出信号。
<li>返回的线程的锁重新获取的顺序是
的等待方法与最初的线程相同。
获取锁,在默认情况下是不指定的。
但对于<em>公平的</em>锁来说,更倾向于那些已经被<em>公平</em>锁定的线程。
等得最久。
@return the Condition object
/
public Condition newCondition() {
return sync.newCondition();
}
/**
Queries the number of holds on this lock by the current thread.
<p>A thread has a hold on a lock for each lock action that is not
matched by an unlock action.
<p>The hold count information is typically only used for testing and
debugging purposes. For example, if a certain section of code should
not be entered with the lock already held then we can assert that
fact:
查询当前线程对该锁的持有数量。
<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 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();
}
/**
Queries if this lock is held by the current thread.
<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();
}
/**
Queries if this lock is held by any thread. This method is
designed for use in monitoring of the system state,
not for synchronization control.
查询该锁是否被任何线程持有。该方法是用于监测系统状态。不用于同步控制。
@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;
}
/**
Returns the thread that currently owns this lock, or
{@code null} if not owned. When this method is called by a
thread that is not the owner, the return value reflects a
best-effort approximation of current lock status. For example,
the owner may be momentarily {@code null} even if there are
threads trying to acquire the lock but have not yet done so.
This method is designed to facilitate construction of
subclasses that provide more extensive lock monitoring
facilities.
返回当前拥有此锁的线程,或
{@code null},如果不拥有。当这个方法被一个
的线程,返回值反映了一个非所有者的
当前锁定状态的最佳近似值。例如:
即使有,所有者可能暂时{@code null},即使有
试图获得锁的线程,但还没有这样做。
这种方法的目的是为了方便构建
子类,提供更广泛的锁监控
设施。
momentarily 刹那间
@return the owner, or {@code null} if not owned
/
protected Thread getOwner() {
return sync.getOwner();
}
/**
Queries whether any threads are waiting to acquire this lock. Note that
because cancellations may occur at any time, a {@code true}
return does not guarantee that any other thread will ever
acquire this lock. This method is designed primarily for use in
monitoring of the system state.
查询是否有线程在等待获取此锁。需要注意的是因为随时都可能发生取消,所以{@@code true}。
返回并不保证任何其他的线程都会获得此锁。 这种方法主要用于 系统状态的监测。
@return {@code true} if there may be other threads waiting to
acquire the lock
/
public final boolean hasQueuedThreads() {
return sync.hasQueuedThreads();
}
/**
Queries whether the given thread is waiting to acquire this
lock. Note that because cancellations may occur at any time, a
{@code true} return does not guarantee that this thread
will ever acquire this lock. This method is designed primarily for use
in monitoring of the system state.
查询给定的线程是否正在等待获取这个
锁定。请注意,由于随时都可能发生取消,所以
{@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); 查询给定的线程是否正在等待获取这个
锁定,即看它释放已经入队
}
/**
Returns an estimate of the number of threads waiting to
acquire this lock. The value is only an estimate because the number of
threads may change dynamically while this method traverses
internal data structures. This method is designed for use in
monitoring of the system state, not for synchronization
control.
又是监测系统
@return the estimated number of threads waiting for this lock
/
public final int getQueueLength() { 获取同步状态等待的线程的个数
return sync.getQueueLength();
}
/**
Returns a collection containing threads that may be waiting to
acquire this lock. Because the actual set of threads may change
dynamically while constructing this result, the returned
collection is only a best-effort estimate. The elements of the
returned collection are in no particular order. This method is
designed to facilitate construction of subclasses that provide
more extensive monitoring facilities.
又是监测系统
@return the collection of threads
/
protected Collection<Thread> getQueuedThreads() { 获取同步状态等待的线程的集合
return sync.getQueuedThreads();
}
/**
Queries whether any threads are waiting on the given condition
associated with this lock. Note that because timeouts and
interrupts may occur at any time, a {@code true} return does
not guarantee that a future {@code signal} will awaken any
threads. This method is designed primarily for use in
monitoring of the system state.
查询是否有线程在等待给定的条件。
与此锁相关联。请注意,由于超时和
中断可能在任何时候发生,{@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);
}
/**
Returns an estimate of the number of threads waiting on the
given condition associated with this lock. Note that because
timeouts and interrupts may occur at any time, the estimate
serves only as an upper bound on the actual number of waiters.
This method is designed for use in monitoring of the system
state, not for synchronization control.
又是监测系统
@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);
}
/**
Returns a collection containing those threads that may be
waiting on the given condition associated with this lock.
Because the actual set of threads may change dynamically while
constructing this result, the returned collection is only a
best-effort estimate. The elements of the returned collection
are in no particular order. This method is designed to
facilitate construction of subclasses that provide more
extensive condition monitoring facilities.
@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() + "]");
}
}

 

 

以上,请耐心看

 

版权声明
本文为[CanntBelieve]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/FlyAway2013/p/12650828.html