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