我自己找到了一些答案.要测试当前线程是否包含监视器,
Thread.holdsLock存在!
if (!Thread.holdsLock(data)) {
throw new RuntimeException(); // complain
}
这非常快(亚微秒),从1.4开始就可以使用.
为了测试一般情况下,哪个线程(或线程ID)持有锁,可以使用java.lang.management类来执行此操作(感谢@amicngh).
public static long getMonitorOwner(Object obj) {
if (Thread.holdsLock(obj)) return Thread.currentThread().getId();
for (java.lang.management.ThreadInfo ti :
java.lang.management.ManagementFactory.getThreadMXBean()
.dumpAllThreads(true, false)) {
for (java.lang.management.MonitorInfo mi : ti.getLockedMonitors()) {
if (mi.getIdentityHashCode() == System.identityHashCode(obj)) {
return ti.getThreadId();
}
}
}
return 0;
}
这有几点需要注意:
>它有点慢(在我的情况下约为1/2毫秒,并且可能与线程数呈线性增加).
>它需要Java 1.6,以及ThreadMXBean.isObjectMonitorUsageSupported()为true的VM,因此它的可移植性较差.
>它需要“监视器”安全权限,因此可能无法使用沙盒applet.
>如果需要,将线程ID转换为Thread对象,有点不重要,因为我想你必须使用Thread.enumerate,然后循环查找哪个有ID,但这有理论竞争条件,因为当你调用enumerate时,该线程可能不再存在,或者可能出现了具有相同ID的新线程.
但是如果你只想测试当前的线程,Thread.holdsLock效果很好!否则,java.util.concurrent.locks.Lock的实现可以提供比普通Java监视器更多的信息和灵活性(感谢@ user1252434).