为什么未将java.util.concurrent.locks.AbstractOwnableSynchronizer.exclusiveOwnerThread声明为易失性?

问题描述 投票:0回答:1

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

我们尝试“拥有”该锁,或者检查我们是否已经拥有该锁,具体取决于state中维护的AbstractQueuedSynchronizer。但是我想知道为什么变量state声明为volatile,而变量exclusiveOwnerThread却没有声明吗?谢谢!

java volatile reentrantlock
1个回答
0
投票
为了理解为什么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)时,才为真。一个线程中的动作总是

happen-before同一线程中的后续动作。

因此,如果c != 0则有两种情况:

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

      由于一个线程中的操作总是
    • happen-before
同一线程中的后续操作,因此可以保证getExclusiveOwnerThread()将返回对调用线程的引用。
  • 调用线程

  • 拥有同步器。
    • getExclusiveOwnerThread()返回什么引用不再重要,因为该方法将对引用的引用返回给调用线程

      不可能

    由于setExclusiveOwnerThread(null)中的#tryRelease(int)调用,因此调用线程永远无法看到对其自身的陈旧引用。这意味着getExclusiveOwnerThread()可以返回null或其他一些Thread引用(是否过期),但永远不能返回对调用线程的引用。


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

    © www.soinside.com 2019 - 2024. All rights reserved.