阻塞的线程可以重新安排去做其他工作吗?

alf*_*fer 4 java multithreading operating-system

如果我有一个线程被阻塞等待锁,操作系统可以重新安排该线程去做其他工作,直到锁可用吗?根据我的理解,它不能被重新安排,它只是闲置直到它能够获取锁。但这似乎效率很低。如果我们有 100 个任务提交给 ExecutorService,并且池中有 10 个线程:如果其中一个线程持有锁,而其他 9 个线程正在等待该锁,则只有持有锁的线程才能取得进展。我本以为被阻塞的线程可以暂时重新安排来运行其他一些提交的任务。

Bas*_*que 5

你说:

\n
\n

我本以为被阻塞的线程可以暂时重新安排来运行其他一些提交的任务。

\n
\n

织机计划

\n

您恰好描述了作为Project Loom 的一部分为未来 Java 版本开发的虚拟线程(纤程)。

\n

目前,Java 的 OpenJDK 实现使用主机操作系统中的线程作为 Java 线程。所以这些线程的调度实际上是由操作系统而不是JVM控制的。是的,正如您所描述的,在所有常见操作系统上,当 Java 代码阻塞时, code\xe2\x80\x99s 线程处于空闲状态。

\n

Project Loom 在 \xe2\x80\x9creal\xe2\x80\x9d 平台/内核线程之上分层虚拟线程。许多虚拟线程可以映射到每个真实线程。在通用硬件上运行数百万个线程是可能的。

\n

借助 Loom 技术,JVM 可以检测阻塞代码。被阻止的代码\xe2\x80\x99s 虚拟线程是\xe2\x80\x9cparked\xe2\x80\x9d,放在一边,另一个虚拟线程分配给该真实线程,以在停放线程等待响应时完成一些执行时间。这种停车和切换速度相当快,开销很小。在Loom技术下阻塞变得极其\xe2\x80\x9ccheap\xe2\x80\x9d。

\n

阻塞在大多数普通的面向业务的应用程序中非常常见。文件 I/O、网络 I/O、数据库访问、日志记录、控制台交互、GUI 等都会发生阻塞。此类使用虚拟线程的应用程序通过 Project Loom 的实验版本获得了巨大的性能提升。这些版本现已推出,基于抢先体验的 Java 17。Project Loom 团队正在寻求反馈。

\n

使用虚拟线程非常简单:切换您选择的执行程序服务。

\n
ExecutorService executorService = Executors.newVirtualThreadExecutor() ;\n
Run Code Online (Sandbox Code Playgroud)\n

警告:正如Michael 所评论的,JVM 管理的虚拟线程依赖于主机操作系统管理的平台/内核线程。最终,即使在 Loom 下,执行也是由操作系统调度的。当阻塞的 Java 线程在 CPU 核心上闲置时,虚拟线程非常有用。如果主机负担过重,无论是否有虚拟线程,Java 线程的执行时间都可能很少。

\n

虚拟线程不适合很少阻塞、真正受CPU 限制的任务。例如,对视频进行编码。此类任务应继续使用传统线程。

\n

有关更多信息,请参阅 Oracle 的 Ron Pressler 或 Loom 团队其他成员的启发性演示和访谈。随着 Loom 的发展,寻找最新的。

\n