这是我回答自己问题的尝试。
我认为以下条件应该足以使单个线程安全停止使用:Thread.stop()
- 线程执行不得创建或改变任何状态(即 Java 对象、类变量、外部资源),这些状态在线程停止时可能对其他线程可见。
- 线程执行在其正常执行期间不得用于任何其他线程。
notify
- 该线程不得或其他线程,或者与之交互然后使用 、 或 。
start
join
stop
suspend
resume
(上面的术语“线程执行”涵盖线程执行的所有应用程序级代码和所有库代码。
第一个条件意味着停止的线程不会使任何外部数据结构或资源处于不一致状态。这包括它可能在互斥体中访问(读取)的数据结构。第二个条件意味着可停止线程不能让其他线程等待。但它也禁止使用简单对象互斥锁以外的任何同步机制。
可停止线程必须有一种方法可以将每个计算的结果传递到控制线程。这些结果是由可停止线程创建/突变的,因此我们只需要确保它们在线程停止后不可见。例如,可以将结果分配给 Thread 对象的私有成员,并使用线程以原子方式表示“完成”的标志进行“保护”。
编辑:这些条件非常严格。例如,对于要安全停止的“正则表达式评估器”线程,如果我们必须保证正则表达式引擎不会改变任何外部可见状态。问题是它可能确实如此,这取决于你如何实现线程!
- 这些方法可能会更新已编译模式的静态缓存,如果它们这样做,它们将(应该)使用互斥体来执行此操作。(实际上,OpenJDK 6.0版本不会缓存Patterns,但Sun可能会改变这一点。
Pattern.compile(...)
- 如果您尝试通过在控制线程中编译正则表达式并提供预实例化来避免 1),则正则表达式线程确实会改变外部可见状态。
Matcher
在第一种情况下,我们可能会遇到麻烦。例如,假设使用 HashMap 来实现缓存,并且在重新组织 HashMap 时线程中断。
在第二种情况下,如果 没有将 传递给其他线程,并且控制器线程在停止正则表达式匹配器线程后没有尝试使用,我们就可以了。Matcher
Matcher
那么,这给我们留下了什么呢?
好吧,我想我已经确定了线程在理论上可以安全停止的条件。我还认为,从理论上讲,静态分析线程的代码(以及它调用的方法)以查看这些条件是否始终有效是可能的。但是,我不确定这是否真的实用。
这有意义吗?我错过了什么吗?
编辑 2
当你考虑到我们可能试图杀死的代码可能是不受信任的时,事情变得更加棘手:
我们不能依赖“承诺”;例如,在不受信任的代码上注释它要么是可杀死的,要么是不可杀死的。
我们实际上需要能够阻止不受信任的代码做一些会让它无法杀死的事情......根据确定的标准。
我怀疑这需要修改JVM行为(例如,实现允许锁定或修改哪些线程的运行时限制),或者隔离JSR的完整实现。这超出了我所认为的“公平游戏”的范围。
因此,让我们暂时排除不受信任的代码情况。或者至少,承认恶意代码可以做一些事情来使自己无法安全地杀死,并将这个问题放在一边。