Java 可重入锁实现细节
我试图理解Java 可重入锁实现细节,java,multithreading,concurrency,reentrantlock,java-15,Java,Multithreading,Concurrency,Reentrantlock,Java 15,我试图理解ReentrantLock::lock方法中的一个特定细节。我将其视为: final void lock() { if (!initialTryLock()) { acquire(1); } } 首先,它尝试了这个方法:initialTryLock(我将在NonfairSync中查找),它执行以下操作: 它做了一个比较的wap(0,1),意思是如果没有人持有锁(0),我可以抓住它(1),我现在就持有锁 如果上述操作失败,它将检查请求锁的线程是否已经是所有者
ReentrantLock::lock
方法中的一个特定细节。我将其视为:
final void lock() {
if (!initialTryLock()) {
acquire(1);
}
}
首先,它尝试了这个方法:initialTryLock
(我将在NonfairSync
中查找),它执行以下操作:
- 它做了一个
,意思是如果没有人持有锁(比较的wap(0,1)
),我可以抓住它(0
),我现在就持有锁1
- 如果上述操作失败,它将检查请求锁的线程是否已经是所有者
- 如果失败,它将返回
,这意味着我无法获得锁false
AbstractQueuedSynchronizer
中调用acquire
:
public final void acquire(int arg) {
if (!tryAcquire(arg))
acquire(null, arg, false, false, false, 0L);
}
它在NonfairSync
中首先调用tryAcquire
:
protected final boolean tryAcquire(int acquires) {
if (getState() == 0 && compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
您可以看到它再次尝试获取锁,尽管initialTryLock
已经失败。理论上,这个tryAcquire
可以简单地返回false
,对吗
我认为这是一次潜在的重试,因为在调用initialTryLock
和tryAcquire
之间,锁可能已被释放。这样做的好处可能是,因为下一个操作(在tryAcquire
失败之后)是该线程的昂贵排队。因此,我想这是有意义的(重试),因为这?
包含可重入功能:initialTryLock()
- javadoc:
/** *检查可重入性并立即获取是否锁定 *根据公平与非公平规则提供。锁定方法 *在中继到之前执行初始锁定检查 *相应的AQS获取方法。 */ 抽象布尔initialTryLock();
中的源代码:NonfairSync
在这里:final boolean initialTryLock(){ 线程当前=Thread.currentThread(); 如果(compareAndSetState(0,1)){//第一次尝试未受保护 设置ExclusiveOwnerThread(当前); 返回true; }else if(getExclusiveOwnerThread()=当前){ int c=getState()+1; if(c<0)//溢出 抛出新错误(“超过最大锁计数”); 设定状态(c); 返回true; }否则 返回false; }
- 第一个
检查锁是否被取下(如果锁是自由的,则取下锁)if
- 第二个
检查获取的锁是否属于当前线程-这是重入逻辑if
- 第一个
- javadoc:
必须由任何扩展tryAcquire()
AbstractQueuedSynchronizer
- 该方法必须执行的操作在
AbstractQueuedSynchronizer
/** *尝试以独占模式获取。这个方法应该是查询 *如果对象的状态允许在 *独占模式,如果是,则获取它。 * ... */ 受保护的布尔值tryAcquire(int arg){ 抛出新的UnsupportedOperationException(); }
中的实现正是这样做的(并且不包含可重入功能):NonfairSync
/** *InitialRylock预筛选后非重入病例的获取 */ 受保护的最终布尔值tryAcquire(整数获取){ if(getState()==0&&compareAndSetState(0,获取)){ setExclusiveOwnerThread(Thread.currentThread()); 返回true; } 返回false; }
- 该方法必须执行的操作在
tryAcquire
可以简单地返回false,对吗
没有
这一实施:
boolean-tryAcquire(整数获取){
返回false;
}
将中断AbstractQueuedSynchronizer的工作
原因是tryAcquire()
是在AbstractQueuedSynchronizer
中锁定的唯一方法
甚至
因此,如果tryAcquire()
始终返回false
,则acquire()
将永远不会获取锁
而
acquire()
在多个线程争用锁时使用。你提到的是哪个版本的java src?@Andrea my bad,我在看jdk-15;在Java12中,ReentrantLock::lock直接调用sync.acquire(1),函数initialTryLock不存在。所以你提到的代码是最近引入的。如果有人要调查,他应该参考正确的javaversion@Andrea说得好。我添加了正确的标签。谢谢,那么什么停止NonfairSync::tryAcquire
返回false
?它是一个具有非公共方法的非公共类。From:tryAcquire()
用于AbstractQueuedSynchronizer
中的多个位置。在您发现的地方,如果tryAcquire()
什么也不做,并返回false
,就可以了。但是在AbstractQueuedSynchronizer
的其他地方,如果tryAcquire()
没有遵守其在javadoc中关于AbstractQueuedSynchronizer::tryAcquire
的合约,它将中断AbstractQueuedSynchronizer
@dan1st right。我希望我错过了它,但是您能发现tryAcquire
后面没有acquire
的AbstractQueuedSynchronizer
中的任何代码流吗?我确实理解遵守javadoc,但是返回false
不会违反这一点。我的意思是,默认实现甚至会引发异常。除此之外,javadoc还表示:尝试以独占模式进行获取,而initialTryLock
已经通过if(compareAndSetState(0,1)实现了这一点
。顺便说一句,你必须在我发表评论时给我贴上@
标签。我在获取
中看到了tryAcquire
的用法,但就我所知,它失败是完全可以的,也就是说:获取
为错误
。这让我起初有点不舒服。我现在看了代码