“无法复现”- Java是否支持确定性多线程?

7

在Java应用程序中以确定性的方式运行多线程应用程序是否可行?我的意思是在两次不同运行中始终具有相同的线程切换。

这样做的原因是为了在每次运行中以完全相同的条件运行模拟。

类似的情况是,当使用随机数生成器时,给定一些任意种子以获得始终相同的“随机”序列。


1
线程调度由操作系统控制,而不是Java。 - Andy Turner
如果您仔细同步了代码,并且只依赖于提前可用的输入,那么它应该始终以相同的方式运行。 (或者反过来说,如果结果取决于每次运行的特定时间,那么您还没有很好地同步代码。)根据您实际需要,您也可以尝试Java VM的实时实现。 - biziclop
1
@biziclop,如果你的程序如此彻底地同步,那么很有可能你已经失去了使用多线程的一些好处。 - Solomon Slow
2
有一个想法已经在流传了相当长的时间(但我不知道它有多少关注度),那就是使用虚拟化环境来强制执行多线程执行的特定序列化。通常的目的是为了测试多线程算法(即证明所有可能的序列化都会正确地运行)。我现在能想到的唯一例子是谷歌的一些人几年前编写的 https://github.com/google/thread-weaver。我不知道它是否好用,或者它擅长什么,但值得一看。 - Solomon Slow
@jameslarge 很有可能,是的。 - biziclop
3个回答

4

我不知道有任何实用的方法来做到这一点。

理论上,在某些假设条件下,可以实现具有完全确定行为的字节码解释器1。您需要通过在软件中完全实现线程和线程调度,并使用单个本地线程来模拟多个线程。


1 - 例如,没有I/O和不使用系统时钟。


您可能还需要实现垃圾回收(GC)。 - biziclop
@biziclop - 也许不需要。你需要担心的与GC相关的非确定性源只有基于内存地址的标识哈希码和终结。我认为这两个问题都可以解决。 - Stephen C

4

除非您自己模拟,否则不可能以相同的方式每次交替使用多个线程。线程不是为此而设计的。

如果您想要确定性结果,请不要使用线程。


0

正如OldCurmudgeon所说,使用多线程是不可能的。

如果您决定使用单个Thread,我建议使用newSingleThreadExecutor而不是普通的Thread,因为newSingleThreadExecutor具有更高的灵活性和优势。

请使用Executors中的newSingleThreadExecutor

public static ExecutorService newSingleThreadExecutor()

创建一个执行器,它使用单个工作线程以无限制队列的方式操作。(请注意,如果此单个线程在关闭前由于执行期间发生故障而终止,则如果需要执行后续任务,将会有一个新的线程代替它。) 任务保证按顺序执行,并且在任何给定时间内,最多只有一个任务处于活动状态。与否则等效的newFixedThreadPool(1)不同,返回的执行器保证不会重新配置以使用额外的线程。

相关SE问题:

Executors.newFixedThreadPool(1)和Executors.newSingleThreadExecutor()之间的区别

ExecutorService vs Casual Thread Spawner


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接