可重入锁实现细节
Reentrant lock implementation detail
我试图了解 ReentrantLock::lock
方法中的特定细节。我正在查看它并将其视为:
final void lock() {
if (!initialTryLock()) {
acquire(1);
}
}
所以首先它会尝试这种方法:initialTryLock
(我会查看 NonfairSync
),这样做是这样的:
- 它做了一个
compareAndSwap(0, 1)
,意思是如果没有人持有锁(0
)而我可以抓住它(1
),我现在持有锁。
- 如果以上失败,它会检查请求锁的线程是否已经是所有者。
- 如果失败 returns
false
,这意味着我无法获取锁。
让我们假设以上失败。然后继续调用 acquire
in AbstractQueuedSynchronizer
:
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()
包含重入功能:
- Java文档:
/**
* Checks for reentrancy and acquires if lock immediately
* available under fair vs nonfair rules. Locking methods
* perform initialTryLock check before relaying to
* corresponding AQS acquire methods.
*/
abstract boolean initialTryLock();
NonfairSync
中的源代码:
final boolean initialTryLock() {
Thread current = Thread.currentThread();
if (compareAndSetState(0, 1)) { // first attempt is unguarded
setExclusiveOwnerThread(current);
return true;
} else if (getExclusiveOwnerThread() == current) {
int c = getState() + 1;
if (c < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(c);
return true;
} else
return false;
}
这里:
- 第一个
if
检查锁是否被占用(如果空闲则获取锁)
- 第二个
if
检查获取的锁是否属于当前线程——这是重入逻辑。
tryAcquire()
必须由任何扩展 AbstractQueuedSynchronizer
的 class 实现
- 该方法必须执行的操作在
AbstractQueuedSynchronizer
的 javadoc 中进行了描述
/**
* Attempts to acquire in exclusive mode. This method should query
* if the state of the object permits it to be acquired in the
* exclusive mode, and if so to acquire it.
* ...
*/
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
NonfairSync
中的实现正是这样做的(并且不包含重入功能):
/**
* Acquire for non-reentrant cases after initialTryLock prescreen
*/
protected final boolean tryAcquire(int acquires) {
if (getState() == 0 && compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
只是添加到 。
tryAcquire
could have simply returned false, right?
没有
这个实现:
boolean tryAcquire(int acquires) {
return false;
}
会破坏 AbstractQueuedSynchronizer
的工作。
原因是tryAcquire()
是在AbstractQueuedSynchronizer
中获取锁的唯一方法。
甚至acquire()
in the end uses tryAcquire()
.
所以如果 tryAcquire()
总是返回 false
那么 acquire()
永远不会获得锁。
而acquire()
用于多个线程争用锁时
我试图了解 ReentrantLock::lock
方法中的特定细节。我正在查看它并将其视为:
final void lock() {
if (!initialTryLock()) {
acquire(1);
}
}
所以首先它会尝试这种方法:initialTryLock
(我会查看 NonfairSync
),这样做是这样的:
- 它做了一个
compareAndSwap(0, 1)
,意思是如果没有人持有锁(0
)而我可以抓住它(1
),我现在持有锁。 - 如果以上失败,它会检查请求锁的线程是否已经是所有者。
- 如果失败 returns
false
,这意味着我无法获取锁。
让我们假设以上失败。然后继续调用 acquire
in AbstractQueuedSynchronizer
:
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()
包含重入功能:- Java文档:
/** * Checks for reentrancy and acquires if lock immediately * available under fair vs nonfair rules. Locking methods * perform initialTryLock check before relaying to * corresponding AQS acquire methods. */ abstract boolean initialTryLock();
NonfairSync
中的源代码:
这里:final boolean initialTryLock() { Thread current = Thread.currentThread(); if (compareAndSetState(0, 1)) { // first attempt is unguarded setExclusiveOwnerThread(current); return true; } else if (getExclusiveOwnerThread() == current) { int c = getState() + 1; if (c < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(c); return true; } else return false; }
- 第一个
if
检查锁是否被占用(如果空闲则获取锁) - 第二个
if
检查获取的锁是否属于当前线程——这是重入逻辑。
- 第一个
- Java文档:
的 class 实现tryAcquire()
必须由任何扩展AbstractQueuedSynchronizer
- 该方法必须执行的操作在
AbstractQueuedSynchronizer
的 javadoc 中进行了描述
/** * Attempts to acquire in exclusive mode. This method should query * if the state of the object permits it to be acquired in the * exclusive mode, and if so to acquire it. * ... */ protected boolean tryAcquire(int arg) { throw new UnsupportedOperationException(); }
NonfairSync
中的实现正是这样做的(并且不包含重入功能):
/** * Acquire for non-reentrant cases after initialTryLock prescreen */ protected final boolean tryAcquire(int acquires) { if (getState() == 0 && compareAndSetState(0, acquires)) { setExclusiveOwnerThread(Thread.currentThread()); return true; } return false; }
- 该方法必须执行的操作在
只是添加到
tryAcquire
could have simply returned false, right?
没有
这个实现:
boolean tryAcquire(int acquires) {
return false;
}
会破坏 AbstractQueuedSynchronizer
的工作。
原因是tryAcquire()
是在AbstractQueuedSynchronizer
中获取锁的唯一方法。
甚至acquire()
in the end uses tryAcquire()
.
所以如果 tryAcquire()
总是返回 false
那么 acquire()
永远不会获得锁。
而acquire()
用于多个线程争用锁时