如代码所示,locksupport.park ()在线程t1中被调用两次。在LockSupport.park ()之后,主线程第一次唤醒线程t1,并使用t1.中断(),然后在t1中调用thread.interrupted ()以清除线程的中断状态。但是Locksupport.park ()不会第二次挂起线程。奇怪的是,在注释掉log.debug(“test.”)之后,locksupport.park ()可以再次暂停线程。原因是什么?
@Slf4j
public class Test08Park4 {
public static void main(String[] args) throws InterruptedException{
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
LockSupport.park();
/**
* With this log print, locksupport.park () cannot stop threads;
* If you comment this out, locksupport.park () can stop the thread
*/
log.debug("test.......");
Thread.interrupted();
LockSupport.park();
log.debug("finished...");
}
});
t1.start();
sleep(1000);
t1.interrupt();
}
}如果不评论log.debug(“测试.”)结果是:
22:37:05.435 [Thread-0] DEBUG test.Test08Park4 - test.......
22:37:05.439 [Thread-0] DEBUG test.Test08Park4 - finished...如果评论log.debug(“测试.”)结果是:
//无
发布于 2022-10-06 14:43:55
阅读文档是基本的。
如文档所示,允许伪造地返回LockSupport.park()。换句话说,这些文档逐字逐句地说明:
洛克苏波特的锁是线程全局的。对于每个线程,只有一个信号量( LockSupport称之为“许可”),您不能做更多,也不能做得更少。基本上意味着,JVM中的一个系统可以使用它,因为如果两个系统使用它,它们就会相互混淆。
正如医生们所言:
创建锁和其他同步类的基本线程阻塞原语。
这实质上意味着:你为什么要这么做?如果您想要锁定行为,请使用例如来自java.util.concurrent包的java.util.concurrent;这不是针对您的,因此它有各种各样的奇怪之处,例如park()的规则允许虚假返回。
log.debug代码很可能是A出于某种原因调用LockSupport.unpark(ownThread),这意味着下一个park()调用会立即返回,或者B是时间问题。log.debug不是“免费的”,许多日志框架运行“就地”,这意味着,log.debug调用实际上会在磁盘和fsyncs上运行,这意味着,与一般的非磁盘交互java指令(相当于数百条指令)相比,这确实需要很长的时间。这个时间对调度器来说已经足够了,特别是考虑到‘写磁盘’或'fsync‘是一个自然的停止点( java中的线程是先发制人的,但是如果您给调度程序一个暂停线程的借口,它通常会占用它)。
最后,文档是清楚的:你没有得到你的“为什么”问题的答案。规范使JVM可以自由支配,而不必向您解释为什么park()虚假地返回。因此,找出这个案子的原因没有多大意义--即使你有答案,明天也会有不同的原因。如果您的代码无法处理LockSupport.park()上的虚假返回,那么根据定义,您的代码就会中断。即使你能让它在你的机器上工作,今天,在月球的这个阶段,这并不能保证它明天会工作得很好。
一旦您的代码能够处理虚假的返回,找出为什么它在这里虚假返回不再有趣了。因此,解决方案:正确处理虚假的回报。或者,更有可能的是,不要将它用于锁,而是使用一些对最终用户更友好的东西。
https://stackoverflow.com/questions/73975470
复制相似问题