简体   繁体   English

JVM线程管理与OS调度

[英]JVM thread management v.s. OS scheduling

As I know, one of the most common JVM concurrency API: futures - at least as implemented in scala - rely on user code to relinquish a thread when it is potentially going to be waiting idle. 据我所知,最常见的JVM并发API之一:期货-至少在scala中实现-依靠用户代码在线程可能等待空闲时放弃线程。 In scala it's commonly referred to as "avoiding blocking", and the developer has to implement it everywhere it makes sense. 在Scala中,通常将其称为“避免阻塞”,开发人员必须在有意义的任何地方实施它。 Not quite efficient. 不太有效。

Is there something very entirely inherent to the JVM, that prevents the JVM switching the context of a thread to new tasks - when the thread is idle - as implemented by operating system process schedulers? JVM是否具有完全内在的功能,可以防止JVM将线程的上下文切换到新任务(当线程空闲时)(由操作系统进程调度程序实现)?

Is there something very entirely inherent to the JVM, that prevents the JVM switching the context of a thread to new tasks - when the thread is idle - as implemented by operating system process schedulers? JVM是否具有完全内在的功能,可以防止JVM将线程的上下文切换到新任务(当线程空闲时)(由操作系统进程调度程序实现)?

Mostly the need that such switch has to be done cooperatively. 大多数情况下,这种切换必须合作完成。 Every single blocking method must be wrapped or re-implemented in a way that allows the task to be resumed once it is done, after all, there is no native thread waiting for completion of the blocking action anymore. 每个单一的阻塞方法都必须以某种方式包装或重新实现,以使该任务一旦完成就可以恢复。毕竟,不再有本机线程等待阻塞操作的完成。

While this can be done in principle for JVM-internal blocking methods, consider arbitrary native code executed via JNI, the JVM wouldn't know how to stack-switch those native threads, they're stuck in native code after all. 尽管原则上可以针对JVM内部阻止方法完成此操作,但考虑通过JNI执行的任意本机代码,JVM不会知道如何对这些本机线程进行堆栈切换,但是它们毕竟卡在了本机代码中。

You might want to have a look at quasar , as I understand it they implemented such wrappers or equivalents for some JDK-internal methods, such as sleep , park / unpark , channel-based-IO and a bunch of others which allows their fibers (and thus futures running on those fibers) to perform exactly that kind of user-mode context switching while they wait for completion. 您可能想看一下类星体 ,据我了解, 类星体为某些JDK内部方法实现了此类包装程序或等效类,例如sleeppark / unpark ,基于channel的IO以及一堆其他允许它们使用光纤的方法(因此在这些光纤上运行的期货)可以在等待完成时准确执行这种用户模式上下文切换。

Edit: JNI alone already is sufficient to limit user-mode task switching to being an opportunistic optimization that may have to fall back to spinning up additional native threads when native code blocks a thread. 编辑:仅JNI便已足以将用户模式任务切换限制为机会优化,当本机代码阻塞线程时,可能必须回落到旋转其他本机线程。

But it is not the only issue, for example on linux truly asynchronous file IO operations need filesystem and kernel support (see this SO question on AIO ), which not all of them provide. 但这不是唯一的问题,例如在linux上,真正的异步文件IO操作需要文件系统和内核支持(请参阅AIO上的SO问题 ),但并非所有人都提供。 Where it is not provided it has to be emulated using additional blocking IO threads, thus re-introducing all the overhead we wanted to avoid in the first place. 如果没有提供,则必须使用其他阻塞的IO线程进行仿真,从而重新引入了我们首先要避免的所有开销。 Might as well just block on the thread pool itself and spin up additional threads, at least we'll avoid inter-thread-communication that way. 最好只是阻塞线程池本身并增加其他线程,至少我们将避免这种方式的线程间通信。

Memory-mapped files can also block a thread and force the OS-scheduler to suspend the thread due to page faults and I'm not aware of means to cooperate with the virtual memory system to avoid that. 内存映射文件还可能阻塞线程,并由于页面错误而迫使OS调度程序挂起线程,我不知道与虚拟内存系统合作避免这种情况的方法。

Not to mention that all blocking calls on the VM would have to re-implemented using asynchronous equivalents provided by the OS. 更不用说VM上的所有阻塞调用都必须使用OS提供的异步等效项来重新实现。 Miss even one and you'll have a blocked thread. 甚至错过一个,您的线程就会被阻塞。 If you have a blocked thread your thread pools will need an auto-grow feature and we're back to square one. 如果线程被阻塞,则线程池将需要自动增长功能,我们将回到正题。

Last but not least, there may be cases where blocking, one-thread-per-filedescriptor IO may be desirable. 最后但并非最不重要的一点是,在某些情况下可能需要阻塞每个文件描述符一个线程IO。 The pervasive changes required to guarantee user-mode switching might break those. 确保用户模式切换所需的普遍更改可能会破坏这些更改。

So all in all, user mode switching is possible, sometimes . 因此总而言之, 有时可以进行用户模式切换。 But the JVM cannot make hard guarantees about it so it has to implement all the native thread handling anyway and the programmer will have code at least somewhat cooperatively with the assumptions of the thread pools executing those futures in mind. 但是JVM不能对此做出硬性保证,因此无论如何它都必须实现所有本机线程处理,并且程序员将在考虑到线程池执行这些未来的假设的前提下至少在某种程度上具有协作性。 Some of the cases could be eliminated, but not all of them. 有些情况可以消除,但并非全部。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM