aka*_*rma 6 java multithreading synchronization
我试图了解ReentrantLock如何在java中工作.
让我们考虑一个简单的例子如下:
private ReentrantLock lock;
public void foo() {
lock.lock();
try{
...
}finally {
lock.unlock();
}
}
Run Code Online (Sandbox Code Playgroud)
我试图弄清楚lock()方法的调用层次结构.
public void lock() {
sync.lock();
}
Run Code Online (Sandbox Code Playgroud)
对于FairSync:
final void lock() {
acquire(1);
}
Run Code Online (Sandbox Code Playgroud)
对于NonFairSync:
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
Run Code Online (Sandbox Code Playgroud)
两个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();
}
Run Code Online (Sandbox Code Playgroud)
如果当前线程无法获取资源(即某个其他线程已获取此资源),则当前线程必须等待.在这种情况下,ReentrantLock调用selfInterrupt()方法.
现在我的问题是interrupt()方法如何能够停止一个等同于synchronized中的wait()方法的线程?
另外,在资源被另一个线程释放后,currentThread如何自动启动?(在内部调用的另一个线程调用unlock()方法之后sync.release(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();
Run Code Online (Sandbox Code Playgroud)
另外,资源被另一个线程释放后,currentThread如何自动启动?
再次,它利用该LockSupport实用程序unpark
使给定线程的许可可用(如果该许可尚不可用)。如果线程在 Park 时被阻塞,那么它将解除阻塞。