lock()方法在ReentrantLock java

时间:2016-08-27 16:55:36

标签: java multithreading synchronization

我试图了解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);

的另一个线程调用unlock()方法之后

我还试图弄清楚{(3}}中的interrupt()方法是如何工作的,但无法找到我的问题的答案。

1 个答案:

答案 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

  

为给定线程提供许可证(如果尚未提供)   可用。如果线程在停放时被阻止,那么它将解锁。