据我所知,最常见的JVM并发API之一:期货 - 至少在scala中实现 - 依赖于用户代码在可能等待空闲时放弃线程。在scala中,它通常被称为"避免阻塞",开发人员必须在任何有意义的地方实现它。 不太有效率。
JVM是否存在一些非常固有的东西,它阻止JVM将线程上下文切换到新任务 - 当线程空闲时 - 由操作系统进程调度程序实现?
答案 0 :(得分:0)
JVM是否存在一些非常固有的东西,它阻止JVM将线程上下文切换到新任务 - 当线程空闲时 - 由操作系统进程调度程序实现?
主要是需要合作完成这种切换。必须以允许任务完成后恢复的方式包装或重新实现每个阻塞方法,毕竟,没有本机线程等待阻塞操作的完成。
虽然这可以原则上用于JVM内部阻塞方法,但考虑通过JNI执行的任意本机代码,JVM不知道如何堆叠切换这些本机线程,它们会卡在本机中毕竟是代码。
您可能希望查看quasar,因为我了解它们为某些JDK内部方法实现了这样的包装或等价物,例如sleep
,park
/ {{ 1}},基于通道的IO和其他一些允许其光纤(以及因此在这些光纤上运行的光纤)在等待完成时执行这种用户模式上下文切换的其他内容。
编辑:单独使用JNI 足以将用户模式任务切换限制为机会优化,当本机代码阻塞线程时,可能必须回退到启动其他本机线程。
但这不是唯一的问题,例如在Linux上真正的异步文件IO操作需要文件系统和内核支持(参见本SO question on AIO),但并非所有这些都提供。如果没有提供它,则必须使用额外的阻塞IO线程进行模拟,从而首先重新引入我们想要避免的所有开销。也可能只是阻塞线程池本身并启动其他线程,至少我们会避免这种线程间的通信。
内存映射文件也可以阻塞线程并强制OS调度程序因页面错误而挂起线程,并且我不知道与虚拟内存系统合作以避免这种情况。
更不用说VM上的所有阻塞调用都必须使用操作系统提供的异步等效项重新实现。想念一个,你就会有一个被阻止的线程。如果你有一个被阻塞的线程,你的线程池将需要一个自动增长功能,我们将回到原点。
最后但并非最不重要的是,可能存在阻塞,每个文件一个线程描述符IO可能需要的情况。保证用户模式切换所需的普遍变化可能会破坏这些变化。
总而言之,用户模式切换是可能的,有时。但是JVM无法对其做出硬性保证,因此无论如何它必须实现所有本机线程处理,并且程序员将至少在某种程度上与执行这些未来的线程池的假设合作。有些案例可以被删除,但不是全部。