lock()方法如何在ReentrantLock java中工作

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);)

我也试图找出如何中断()方法的工作原理在这里却找不到答案,我的问题.

Sot*_*lis 1

如果当前线程无法获取资源(即另一个线程已获取该资源),则当前线程必须等待。在这种情况下ReentrantLock调用selfInterrupt()方法。

不,如果tryAcquire返回falseacquireQueued将被调用。在内部,该方法用于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 时被阻塞,那么它将解除阻塞。