阅读java.util.concurrent.locks.ReentrantLock
的源代码时,我发现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;
}
我们尝试“拥有”该锁,或者检查我们是否已经拥有该锁,具体取决于state
中维护的AbstractQueuedSynchronizer
。但是我想知道为什么变量state
声明为volatile,而变量exclusiveOwnerThread
却没有声明吗?谢谢!
exclusiveOwnerThread
不需要是易变的,因此有助于同时查看获取和释放方法。获取方法
1:
/**
* Performs non-fair tryLock. tryAcquire is implemented in
* subclasses, but both need nonfair try for trylock method.
*/
@ReservedStackAccess
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;
}
发布方法:
@ReservedStackAccess 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; }
认识到exclusiveOwnerThread
不会引用与所涉及的线程无关的任意对象也很重要。它专门持有对Thread
实例的引用,并严格与调用线程进行比较。换句话说,重要的是:
Thread.currentThread() == getExclusiveOwnerThread()
[且仅当由于#setExclusiveOwnerThread(Thread)
和#nonfairTryAcquire(int)
的组合性质,且仅在调用线程先前以其自身作为参数调用#tryRelease(int)
时,才为真。一个线程中的动作总是happen-before同一线程中的后续动作。
因此,如果c != 0
则有两种情况:同一线程中的后续操作,因此可以保证
- 调用线程拥有同步器。
由于一个线程中的操作总是
- happen-before
getExclusiveOwnerThread()
将返回对调用线程的引用。调用线程 拥有同步器。不
。 由于
getExclusiveOwnerThread()
返回什么引用不再重要,因为该方法将对引用的引用返回给调用线程不可能
setExclusiveOwnerThread(null)
中的#tryRelease(int)
调用,因此调用线程永远无法看到对其自身的陈旧引用。这意味着getExclusiveOwnerThread()
可以返回null
或其他一些Thread
引用(是否过期),但永远不能返回对调用线程的引用。1。
FairSync#tryAcquire(int)
的实现几乎具有相同的实现,只是它考虑了调用线程的顺序。