我试图了解ReentrantLock如何在java中运行。
让我们考虑一个简单的例子:
private ReentrantLock lock;
public void foo() {
lock.lock();
try{
...
}finally {
lock.unlock();
}
}
我试图弄清楚lock()方法的调用层次结构。
public void lock() {
sync.lock();
}
对于FairSync:
final void lock() {
acquire(1);
}
对于NonFairSync:
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
两个lock()方法都使用参数1调用acquire()方法。
在AbstractQueuedSynchronizer类中:
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
static void selfInterrupt() {
Thread.currentThread().interrupt();
}
如果当前线程无法获取资源(即某个其他线程已获取此资源),则当前线程必须等待。在这种情况下,ReentrantLock调用selfInterrupt()方法。
现在我的问题是interrupt()方法如何能够停止一个等同于wait中的wait()方法的线程?
另外,在资源被另一个线程释放后,currentThread如何自动启动? (在内部调用sync.release(1);
)
我还试图弄清楚{(3}}中的interrupt()方法是如何工作的,但无法找到我的问题的答案。
答案 0 :(得分:1)
如果当前线程无法获取资源(即某个其他线程) 已获得此资源),然后当前线程必须等待。在这 案例
ReentrantLock
调用selfInterrupt()
方法。
不,如果tryAcquire
返回false
,则会调用acquireQueued
。在内部,该方法使用LockSupport#park
来取消计划线程。 javadoc陈述
如果许可证可用,则它被消耗并且呼叫返回 立即;否则当前线程被禁用为线程 调度目的和休眠直到三件事之一 发生:
- [..]
- 其他一些线程中断当前线程;
在这种情况下它实际上不会抛出InterruptedException
,该方法只会返回。要检查相应的线程是否因中断而被唤醒,它必须使用Thread#interrupted()
返回true或false,取决于,但也清除相应Thread
实例上的中断标志强>
因此,acquireQueued
会传播中断的值,并acquire
重置interrupt
上的Thread
标记,如果需要的话,只需要一小段代码
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
此外,在资源被另一个线程释放后,如何 currentThread会自动启动吗?
同样,它使用LockSupport
实用程序和unpark
为给定线程提供许可证(如果尚未提供) 可用。如果线程在停放时被阻止,那么它将解锁。