【问题标题】:Is this a thread safe way to handle blocking close?这是处理阻塞关闭的线程安全方法吗?
【发布时间】:2014-05-17 09:58:33
【问题描述】:

一个线程打开一个资源,这是一个阻塞操作。如果成功,则需要线程再次关闭它,这又是阻塞的,但总是在有限的时间内成功。

可以使用一个标志(我们称之为hasResource),它不能以任何方式与其他线程同步,来表示线程不想被中断。根本不允许其他同步。

以下是处理这种情况的安全方法吗?

@Override // we're subclassing Thread
public void run () {
    try {
        while (!interrupted ()) {
            blockingOpen ();
            // glitch possibility in this line
            hasResource = true;
            blockingClose ();
            hasResource = false;
        }
    }
    catch (final InterruptedException e) {
        interrupt ();
    }
}

特别是,这是否确保线程在拥有资源时不会被中断?

据我所知,只有一个错误机会窗口,即在打开之后和设置标志之前。但是,这似乎不会导致资源泄漏,而是会意外忽略中断请求。有没有可能防止这种情况发生?

【问题讨论】:

  • 实际上,关于我的最后一段,如果线程在睡眠开始时已经被中断,Thread.sleep() 是否会抛出 IE?那会改变一些事情。 javadoc 没有明确说明任何一种方式。
  • 作为单独的问题添加:stackoverflow.com/questions/23710025
  • 您是否尝试在中断后在睡眠期间中断?我想这种行为更容易测试,并有助于得到原始问题的答案。
  • 现在就这样做:)
  • 有趣的是,如果提前设置了中断单位,则尝试睡眠会引发。

标签: java multithreading interrupted-exception


【解决方案1】:

原来的代码其实是正确的。设置 bool 标志不是问题,即使问题错误地暗示它可能是。要明确这一点,需要考虑两点:

首先,行本身不会导致错误。如果打开成功,标志设置 - 总是。甚至 StackOverflow 或 OutOfMemory 都不能在此处合理地发生。

其次,如果在没有执行可中断代码(例如睡眠)的情况下调用 interrupt(),则将设置 interrupted 标志。下一次任何可中断的代码开始执行时,都会检查这个标志,而不是运行代码,而是抛出一个 Interrupted 异常。

因此,原始代码确实按预期工作。

【讨论】:

  • 啊,现在我知道你当时的问题是什么了。这仍然没有解决关闭资源的问题,但我想,原来的问题并不真正需要它。
【解决方案2】:

可以使用一个标志(我们称之为hasResource),它不能以任何方式与其他线程同步,来表示线程不想被中断。根本不允许其他同步。

不,不是。

这是否确保线程在拥有资源时不会被中断?

没有。 如果hasResourcevolatile 并且你所有其他线程都知道hasResource并且观察它,那么你已经抑制了自己调用Thread.interrupt(),但您并没有禁止Java这样做。

为什么您的应用程序线程会相互中断是另一个问题。 20 年来从未使用过此功能。

【讨论】:

  • 其实在这种特殊情况下Thread.interrupt()可以被禁止——因为@mafu覆盖了线程,所以他也可以覆盖Thread.interrupt()来检查标志并在必要时忽略中断。顺便说一句,“20 年来从未使用过此功能”——您从未使用过 Executor 或 Future 吗? Java 中的大多数线程框架都使用线程中断来取消任务。它可能不受服务器程序员的欢迎,但是当桌面/移动程序员忽略它时,我们最终会遇到诸如不间断挂起下载或编译任务之类的奇迹,这些奇迹无法停止数小时。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-16
  • 2013-12-02
  • 1970-01-01
  • 1970-01-01
  • 2010-10-11
相关资源
最近更新 更多