”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 探索 JVM 虚拟线程机制中的固定

探索 JVM 虚拟线程机制中的固定

发布于2024-11-08
浏览:748

Java 的虚拟线程提供了传统操作系统线程的轻量级替代方案,从而实现了高效的并发管理。但了解他们的行为对于获得最佳表现至关重要。这篇博文深入探讨了固定(一种可能影响虚拟线程执行的场景),并探讨了监控和解决该问题的技术。

虚拟线程:一种轻量级并发方法

Java 的虚拟线程是运行在底层操作系统线程(载体线程)之上的托管实体。与创建大量操作系统线程相比,它们提供了一种更有效的处理并发的方法,因为它们产生的开销较低。 JVM动态地将虚拟线程映射到承载线程,从而更好地利用资源。

  • 由 JVM 管理:与操作系统直接管理的 OS 线程不同,虚拟线程由 Java 虚拟机 (JVM) 创建和调度。这允许在 JVM 环境中进行更细粒度的控制和优化。

  • 减少开销:与操作系统线程相比,创建和管理虚拟线程所产生的开销显着降低。这是因为 JVM 可以利用较少数量的底层操作系统线程来有效管理更大的虚拟线程池。

  • 与现有代码的兼容性:虚拟线程被设计为与现有Java代码无缝集成。它们可以与传统操作系统线程一起使用,并在 Executor 和 ExecutorService 等熟悉的结构中工作,用于管理并发。

下图展示了虚拟线程和平台线程的关系:

Exploring Pinning in JVM


固定:当虚拟线程卡住时

当虚拟线程与其承载线程绑定时,就会发生固定。这本质上意味着虚拟线程在处于固定状态时不能被抢占(切换到另一个承载线程)。以下是触发固定的常见场景:

  • 同步块和方法:在同步块或方法中执行代码会导致固定。这确保了对共享资源的独占访问,防止数据损坏问题。

代码示例:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {

  public static void main(String[] args) throws InterruptedException {

    final Counter counter = new Counter();

    Runnable task = () -> {
      for (int i = 0; i 



在此示例中,当虚拟线程进入同步块时,它会固定到其承载线程,但这并不总是正确的。仅Java的synchronized关键字不足以导致虚拟线程中的线程固定。为了发生线程固定,同步块内必须有一个阻塞点,该阻塞点会导致虚拟线程触发暂停,并最终不允许从其承载线程卸载。线程固定可能会导致性能下降,因为它会抵消使用轻量级/虚拟线程的好处。

每当虚拟线程遇到阻塞点时,其状态就会转换为 PARKING。这种状态转换是通过调用 VirtualThread.park() 方法来指示的:

// JDK core code
void park() {
  assert Thread.currentThread() == this;
  // complete immediately if parking permit available or interrupted
  if (getAndSetParkPermit(false) || interrupted)
    return;
  // park the thread
  setState(PARKING);
  try {
    if (!yieldContinuation()) {
      // park on the carrier thread when pinned
      parkOnCarrierThread(false, 0);
    }
  } finally {
    assert (Thread.currentThread() == this) && (state() == RUNNING);
  }
}

让我们看一个代码示例来说明这个概念:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {

  public static void main(String[] args) {

    Counter counter = new Counter();

    Runnable task = () -> {
      for (int i = 0; i 



  • 本机方法/外部函数:运行本机方法或外部函数也可能导致固定。在这些操作期间,JVM 可能无法有效管理虚拟线程的状态。

使用 -Djdk.tracePinnedThreads=full 监视固定

-Djdk.tracePinnedThreads=full 标志是一个 JVM 启动参数,它提供有关虚拟线程固定的详细跟踪信息。启用后,它会记录以下事件:

  • 固定涉及的虚拟线程ID
  • 虚拟线程固定的承载线程ID
  • 堆栈跟踪指示导致固定的代码部分

仅在调试会话期间明智地使用此标志,因为它会带来性能开销。

  1. 编译我们的演示代码:

    javac Main.java
    
  2. 使用 -Djdk.tracePinnedThreads=full 标志启动编译的代码:

    java -Djdk.tracePinnedThreads=full Main
    
  3. 观察控制台中的输出,其中显示了有关虚拟线程固定的详细信息:

    Thread[#29,ForkJoinPool-1-worker-1,5,CarrierThreads]
    java.base/java.lang.VirtualThread$VThreadContinuation.onPinned(VirtualThread.java:183)
    java.base/jdk.internal.vm.Continuation.onPinned0(Continuation.java:393)
    java.base/java.lang.VirtualThread.parkNanos(VirtualThread.java:621)
    java.base/java.lang.VirtualThread.sleepNanos(VirtualThread.java:791)
    java.base/java.lang.Thread.sleep(Thread.java:507)
    Counter.increment(Main.java:38) 
    
    

使用可重入锁修复固定

固定是一种不良情况,它会影响虚拟线程的性能。可重入锁是抵消固定的有效工具。以下是如何使用可重入锁来缓解锁定情况:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;

public class Main {

  public static void main(String[] args) {

    Counter counter = new Counter();

    Runnable task = () -> {
      for (int i = 0; i 



在更新的示例中,我们使用 ReentrantLock 而不是同步块。线程可以获取锁并在完成操作后立即释放它,与可能持有锁较长时间的同步块相比,可能会减少锁定的持续时间。

综上所述

Java 的虚拟线程证明了该语言的发展和功能。它们为传统操作系统线程提供了一种全新的、轻量级的替代方案,为高效的并发管理提供了一座桥梁。花时间深入挖掘并理解线程固定等关键概念可以让开发人员掌握充分利用这些轻量级线程潜力的专业知识。这些知识不仅帮助开发人员为利用即将推出的功能做好准备,还使他们能够在当前项目中更有效地解决复杂的并发控制问题。

版本声明 本文转载于:https://dev.to/yanev/exploring-pinning-in-jvms-virtual-thread-mechanism-5h13?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 如何查找一个数据帧中存在但另一个数据帧中不存在的行(比较 df1 和 df2)?
    如何查找一个数据帧中存在但另一个数据帧中不存在的行(比较 df1 和 df2)?
    比较数据帧:查找一个中存在但另一个中不存在的行比较数据帧以识别差异对于数据质量保证和合并至关重要运营。在本例中,我们有两个具有特定结构的数据帧(df1 和 df2),需要确定 df2 中存在但 df1 中不存在的行。最初,尝试使用 df1 != df2 比较数据帧,结果是一个错误。此方法仅适用于具有...
    编程 发布于2024-11-08
  • CSS 中的动画
    CSS 中的动画
    CSS中的动画有两部分 - @keyframes和animation-*。 @keyframes at 规则 第一部分要求我们定义@keyframes。 这让我们可以指定应在动画持续时间的不同点应用的 CSS 样式。 不同的时间点以百分比值指定。可以指定 0 到 100% 之间的任意...
    编程 发布于2024-11-08
  • 模拟数据生成器:高效软件测试的关键
    模拟数据生成器:高效软件测试的关键
    模拟数据生成在软件测试和开发中发挥着至关重要的作用,使团队能够在不依赖实时数据的情况下模拟真实场景。无论您是测试新功能还是开发 API,模拟数据都有助于简化流程,确保测试一致、可靠,而无需访问生产数据库。 在本文中,我们将深入探讨模拟数据生成器是什么、为什么它们很重要、如何实现它们以及当今开发人员...
    编程 发布于2024-11-08
  • 模拟请求
    模拟请求
    冷静一点,提交者王,我不会谈论 JSON-Server,但它值得留下来! 每个前端都会经历模拟端点请求的需要,有时是因为后端还没有完成其工作,有时是为了调试和模拟特定情况,这在日常生活中很常见。 是的,JSON-Server 令人难以置信并且使用起来非常简单,但是几天前我遇到了一个非常具体的问题,最...
    编程 发布于2024-11-08
  • 如何在 PHP 中迭代遍历和处理子目录内的文件?
    如何在 PHP 中迭代遍历和处理子目录内的文件?
    如何在PHP中遍历子目录并迭代处理文件在PHP中,遍历子目录并迭代处理文件可以使用RecursiveDirectoryIterator和RecursiveIteratorIterator来实现。让我们了解如何根据需要构建代码:// Initializing the path to the main ...
    编程 发布于2024-11-08
  • 瘾君子 # 何时使用效果、Angular DI 功能、请求缓存等
    瘾君子 # 何时使用效果、Angular DI 功能、请求缓存等
    ?嘿,Angular Addict 伙伴 这是 Angular Addicts Newsletter 的第 30 期,这是一本每月精选的引起我注意的 Angular 资源合集。 (这里是第29期、28期、27期) ?发布公告 ?Nx 19.8 更新 ...
    编程 发布于2024-11-08
  • 如何吸引顶尖 Python 开发人员到你的公司
    如何吸引顶尖 Python 开发人员到你的公司
    在竞争激烈的技术领域,吸引顶级 Python 开发人员对于任何希望利用这种多功能编程语言的力量的组织来说至关重要。随着 Python 继续在 Web 开发、数据科学和机器学习等领域占据主导地位,对熟练 Python 开发人员的需求空前高涨。如果您想聘请能够推动创新并为您的项目做出有意义贡献的 Pyt...
    编程 发布于2024-11-08
  • **JavaScript 中 `location = URL` 和 `location.href = URL` 有什么区别?**
    **JavaScript 中 `location = URL` 和 `location.href = URL` 有什么区别?**
    JavaScript:“location = URL”和“location.href = URL”的区别在 JavaScript 中,操作网页的 URL 可以通过以下方式实现两种类似的方法:直接设置 location 属性或设置 location.href 属性。虽然功能可能看起来相同,但这两种方法...
    编程 发布于2024-11-08
  • 如何有效地将PHP变量插入字符串?
    如何有效地将PHP变量插入字符串?
    将 PHP 变量插入字符串将 PHP 变量合并到字符串中时,注意语法以确保所需的输出是至关重要的获得。为了解决这个问题,让我们检查一下提示中显示的代码:目标是包含 $ width 变量在宽度样式属性中,并确保其后跟“px”。不幸的是,尝试用空格分隔变量和“px”或将它们连接在一起会导致错误。解决方案...
    编程 发布于2024-11-08
  • 了解 JavaScript 中下划线 (`_`) 的使用
    了解 JavaScript 中下划线 (`_`) 的使用
    在 JavaScript 中编码时,您可能会遇到用作变量名称的下划线字符 (_),特别是在函数参数中。虽然乍一看似乎很不寻常,但由于各种原因,这种做法在开发人员中很常见。在这篇博文中,我们将探讨下划线代表什么,为什么使用它,以及它在现实示例中的显示方式,例如 coalesceES6 函数。 ...
    编程 发布于2024-11-08
  • 像程序员一样思考:学习 C 基础知识
    像程序员一样思考:学习 C 基础知识
    以程序员思维学习 C 语言:基本语法:变量、数据类型、常量、运算符、控制流。实战案例:计算两个数的平均值,输入两个整数并计算其平均值。以程序员思维思考:用 C 语言学习基础引言学习编程并不难,尤其是当你以程序员思维思考时。本文将从基础开始,用 C 语言引导你逐步了解编程入门知识。C 语言基本语法变量...
    编程 发布于2024-11-08
  • Python 中的列表理解语法何时需要三元运算符?
    Python 中的列表理解语法何时需要三元运算符?
    列表理解难题:可迭代对象中的条件过滤在 Python 中,列表理解提供了一种基于现有可迭代对象创建列表的简洁方法。然而,出现了一个关于涉及 if 语句的列表理解的问题。目标是比较两个可迭代对象 a 和 b,并仅打印两者中出现的元素。预期的代码如下所示:print([y if y not in b f...
    编程 发布于2024-11-08
  • 使用 MetaTrader 订单管理和市场数据收集进行自动交易
    使用 MetaTrader 订单管理和市场数据收集进行自动交易
    Your AsimovMT class provides a comprehensive interface for interacting with MetaTrader5 (MT5) using Python. However, there are several areas in your c...
    编程 发布于2024-11-08
  • Python 列表的最大大小是多少以及它如何影响功能?
    Python 列表的最大大小是多少以及它如何影响功能?
    Python列表的最大大小:综合分析在Python中,列表是基本的数据结构,可以容纳多个不同类型的元素。它们的多功能性和灵活性使得了解它们的局限性至关重要,特别是在处理大型数据集时。本文探讨了 Python 列表可以达到的最大大小及其对其功能的影响。最大列表大小Python 列表的最大大小已定义通过...
    编程 发布于2024-11-08
  • 托管平台列表:综合指南
    托管平台列表:综合指南
    在数字时代,可靠的托管平台对于任何在线展示都至关重要,无论是个人博客、电子商务网站还是公司网站。有无数的选项可供选择,选择合适的托管平台可能会令人畏惧。本指南将帮助您浏览当今一些最好的托管平台,比较它们的功能、价格和对不同需求的适用性。 1. 蓝色主机 概述:Bluehost 是最受...
    编程 发布于2024-11-08

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3