我正在尝试断言是否使用LockSupport.park(Object blocker)
重新发布阻止程序的监视器锁定对象。也就是说:如果在blocker
上同步的部分中调用,blocker
的监视器锁定是否会被释放?
这是我做的一个junit测试,让我认为是这样的。
我知道一个线程处于状态WAITING
,因为调用了Òbject.waitor LockSupport.park()
,它看起来像使用了相同的底层机制。但是,javadoc没有明确说明我的问题,所以我不确定。
final Object blocker = new Object();
final Thread thread = new Thread() {
@Override
public void run() {
synchronized(blocker) {
while(!interrupted()) {
assertTrue(holdsLock(blocker));
LockSupport.park(blocker);
}
}
}
};
try {
thread.start();
while(thread.getState() != Thread.State.WAITING)
Thread.sleep(100);
assertEquals(0, ManagementFactory.getThreadMXBean().getThreadInfo(thread.getId()).getLockedMonitors().length);
} finally {
thread.interrupt();
}
答案 0 :(得分:2)
简单的答案是否定的。 LockSupport不适用于一般应用程序编程。由于没有保护(与同步等待/通知一起提供),您需要明确控制整个线程环境。也就是说,您不能使用第三方软件并期望它符合您的标准。
有关如何使用park / unpark查看ForkJoinPool源代码的一个很好的示例。
答案 1 :(得分:1)
首先,只需使用以下代码,您的代码就有缺陷了:
ManagementFactory.getThreadMXBean().getThreadInfo(thread.getId())
如文档中所述(它表示此方法等效于调用getThreadInfo(id, 0)
,而后者称为)
...未获得线程的锁定监视器和锁定同步器
因此该数组的长度始终为零。
因此,如果您想要明智的验证代码:
public class DeleteMe3 {
public static void main(String[] args) {
Object lock = new Object();
System.out.println(lock.toString());
Thread thread = new Thread() {
@Override
public void run() {
synchronized (lock) {
boolean holdLock = Thread.holdsLock(lock);
if (!holdLock) {
throw new AssertionError("Does not hold lock");
} else {
System.out.println("I hold the lock");
}
System.out.println("Before parking");
LockSupport.park(lock);
}
}
};
thread.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
showIfAnyLocksHeld(thread.getId());
System.out.println("Unparking... ");
LockSupport.unpark(thread);
}
private static void showIfAnyLocksHeld(long threadId) {
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
ThreadInfo[] infos = bean.getThreadInfo(new long[] { threadId }, true, true);
if (infos.length == 0) {
System.out.println("Thread we are interested in has died");
return;
}
MonitorInfo[] mInfos = infos[0].getLockedMonitors();
if (mInfos.length == 0) {
System.out.println("No locks held by thread " + threadId);
return;
}
System.out.println("Thread with id = " + threadId + " holds lock(s) : " +
Arrays.stream(mInfos).map(MonitorInfo::toString).collect(Collectors.joining(" ; ")));
}
}
输出将包含:
java.lang.Object@5f2108b5
I hold the lock
Before parking
Thread with id = 12 holds lock(s) : java.lang.Object@5f2108b5
因此,您可以说LockSupport.park
将不释放锁;但是如果这样做的话,那将是很奇怪的。除非将其记录下来,否则不会记录。
答案 2 :(得分:0)
如果javadoc没有定义行为,则它是未定义的;)
不要依赖它。