如果线程没有失去任何监视器的所有权,它是不是会导致其他正在运行的线程被阻塞

Posted

技术标签:

【中文标题】如果线程没有失去任何监视器的所有权,它是不是会导致其他正在运行的线程被阻塞【英文标题】:if thread does not lose ownership of any monitors, could it lead other running thread blocked如果线程没有失去任何监视器的所有权,它是否会导致其他正在运行的线程被阻塞 【发布时间】:2022-01-24 04:16:10 【问题描述】:

Thread.sleep()JavaDoc 中声明:

使当前正在执行的线程休眠(暂时停止执行)指定的毫秒数,具体取决于系统计时器和调度程序的精度和准确性。该线程不会失去任何监视器的所有权。

我的问题是:如果线程 A 持有一个监视器并进入睡眠状态,那么线程调度程序将选择另一个可运行的线程 B 并运行它。但是如果线程 B 需要那个监视器,那么它将被阻塞,并且依赖于监视器的任何其他线程都将被阻塞,直到线程 A 从睡眠中恢复并开始运行并释放该监视器,是不是非常低效

【问题讨论】:

是的,它可以阻塞其他线程。是的,它可能效率低下。它可能比“低效”更糟糕。你不应该在拿着显示器的时候打电话给Thread.sleep()。 (实际上,您应该可能完全避免使用sleep()。通常有更好的选择。) 【参考方案1】:

是的。

您还期待什么其他答案?

如果你拿着显示器,显然不要睡觉。而是使用等待和通知。

当您使用等待时会发生以下情况,如果您想使用它,您会调用一个您拥有的对象来保持监视器:

synchronized (foo) 
  do stuff()
  foo.wait();
  do more stuff();

当调用wait() 时,首先,线程释放 监视器。接下来,它只会转动拇指,等待某人,任何人,在同一引用 (foo.notify()) 上调用 notify()。此时,wait() 方法被释放,但仍会等待,因为它现在需要重新获取该监视器才能继续。这不一定会立即发生,因为除非您拿着显示器,否则无法调用 notify()

这很好地解决了您的问题:您可以在释放一个监视器的同时让线程处于休眠状态(但它不会释放其他监视器)。

不过,更一般地说,使用这些低级 API 几乎从来都不是正确的做法。有一些抽象,主要是在java.util.concurrent 包中,它们要好得多。您应该打开 javadoc 并仔细阅读。

【讨论】:

以上是关于如果线程没有失去任何监视器的所有权,它是不是会导致其他正在运行的线程被阻塞的主要内容,如果未能解决你的问题,请参考以下文章

为何stop()和suspend()方法不推荐使用(转)

同步监视器之同步代码块同步方法

对象级别锁 vs 类级别锁 – Java

JavaSE---死锁

关于线程通信

sleep与wait的区别