为什么在应该返回 true 的情况下调用 Thread.holdsLock() 却返回 false?

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

我有一个 Java 程序,它具有一个管理多个相同守护线程的主类。主类有一个守护线程访问的静态

ReentrantLock
。主类创建线程,启动它们,并根据用户输入中断它们。其他线程(都是同一类的实例)被编码为在首先释放锁(如果它们拥有锁)后中断时终止。没有其他代码与锁交互(即使在主类中也没有)。按照我对守护进程类进行编码的方式,守护进程线程在不首先获取锁的情况下不可能执行任何操作。如果
Thread.holdsLock()
没有返回错误的值,则在不首先释放锁的情况下不可能重新获得锁(即保持计数始终为 1 或 0)。我正在运行 Eclipse JavaFX Maven 项目。

这是类的 run() 方法的伪代码示例:

// setup
while(!exitCondition)
  try {
    myLock.lockInterruptibly();
    // do stuff
    if(exitCondition) tellMain(); // this causes main to interrupt all threads
    // sleep for a bit
  } catch (InterruptedException e) {
    // clean up
    break;
  } finally {
     if(Thread.holdsLock(myLock)) myLock.unlock();
  }
}
// termination message

如果我删除 if 语句,则每个不拥有锁的线程都会抛出

IllegalMonitorStateException
。我已经盯着这个问题好几个小时了,没有看到如果调用它的线程拥有锁,Thread.holdsLock() 有任何方法返回 false。管理线程的方法不会以任何方式与锁交互。这是怎么回事?

java multithreading boolean locking
2个回答
1
投票

java中有2个不相关的锁定系统。你将其中一种与另一种混合在一起,这是行不通的。有

java.util.concurrent.Lock
以及所有相关业务,但与它完全无关,“团队同步”,其中包括以下功能:

  • Thread.holdsLock
    <-- there's your problem
  • obj.wait()
    +
    obj.notify
    /
    obj.notifyAll
  • synchronized
    ,关键字。

你正在混合和匹配,这是行不通的。如果你想知道一个线程是否持有juc锁,你不能这样做。它不是 juc lock 的 API 的一部分。

synchronized
更类似于操作系统正在做的事情,juc lock 更抽象一些。特别是考虑到光纤(Loom 项目,JDK21 中的新项目),您可能需要 juc 锁。但是,如果您需要
holdsLock
,您可以自己编写(您可以包装一个锁并注册哪个线程持有它),或者使用低级(“团队同步”)锁。

holdsLock
表示“假”,因为该线程不持有
synchronized
锁。让
Thread.holdsLock(foo)
返回 true 的唯一方法是使用
synchronized (foo) { / * now Thread.holdsLock(foo); will be true */ }

如果您想解锁 Juc 锁,只需这样做,然后抓住如果您从未持有过它就会出现的

IllegalStateException

...但是...

如果您的锁特别是

j.u.c.ReentrantLock
,而且很可能是,那么,您do有一个可以使用的方法。将
Thread.holdsLock(myLock)
替换为
myLock.isHeldByCurrentThread()
。请注意,您的
myLock
param/field/var 需要输入
ReentrantLock
。 RL有这个方法; j.u.c.Lock 没有(该接口尝试应用于尽可能多的实现,也许并非所有实现都希望/能够跟踪哪个线程实际持有它)。


-1
投票

根据Thread#holdsLock

Javadoc:

当且仅当当前线程持有指定对象的监视器锁时返回 true。

监视器锁或内在锁是指

synchronized
关键字(
monitorenter
monitorexit
指令)使用的lovk。

在您的示例中,您使用的

ReentrentLock
与内在锁不同,因此
Thread#holdsLock
不适用。

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