gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 17:50:20 25 4
gpt4 key购买 nike

在阅读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 被声明为 volatile 而变量 exclusiveOwnerThread 却不是?

最佳答案

要理解为什么 exclusiveOwnerThread 不需要是 volatile 的,有助于同时查看 acquire 和 release 方法。

获取方式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( 的组合性质),这才是 true int)#tryRelease(int)。一个线程中的操作总是发生在同一线程中的后续操作之前。

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

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

    • 由于一个线程中的操作总是发生在同一线程中的后续操作之前,因此可以保证 getExclusiveOwnerThread() 将返回对调用线程的引用。
  2. 调用线程拥有同步器。

    • getExclusiveOwnerThread() 返回什么引用不再重要,因为该方法不可能返回对调用线程的引用。

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

state 必须是 volatile 的原因是因为它在线程之间共享,最重要的是每个线程都能看到最新的值。

<小时/>

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

关于java - 为什么 AbstractOwnableSynchronizer.exclusiveOwnerThread 没有声明为 volatile?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60809132/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com