为什么 AbstractOwnableSynchronizer.exclusiveOwnerThread 没有声明为 volatile?

Why AbstractOwnableSynchronizer.exclusiveOwnerThread is not declared as volatile?

在阅读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;
        }

我们尝试“拥有”锁或检查我们是否已经拥有锁,这取决于AbstractQueuedSynchronizer中维护的state。但我想知道为什么变量 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) 的组合性质,这才是正确的.一个线程中的操作始终发生在 同一线程中的后续操作之前。

所以如果c != 0那么有两种情况:

  1. 调用线程拥有同步器。

    • 由于一个线程中的操作总是先于同一线程中的后续操作,因此保证getExclusiveOwnerThread()将return引用调用线程.
  2. 调用线程拥有同步器。

    • getExclusiveOwnerThread() 编辑了什么参考不再重要,因为 不可能 [=80] =] 对调用线程的引用。

      由于 #tryRelease(int) 中的 setExclusiveOwnerThread(null) 调用,调用线程永远看不到对自身的过时引用。这意味着 getExclusiveOwnerThread() 可以 return null 或其他一些 Thread 引用(陈旧与否),但绝不是对调用线程的引用。

state 必须是易变的原因是因为它在线程之间以一种最重要的方式共享,每个线程都能看到最新的值。


1. FairSync#tryAcquire(int) 的实现与实现几乎相同,只是它考虑了调用线程的顺序。