jvm安全点(三)openjdk17 c++源码垃圾回收之安全点结束,唤醒线程

news2025/5/18 16:24:15

1. VMThread::inner_execute() - 触发安全点​

 

cpp

复制

 

void VMThread::inner_execute(VM_Operation* op) { if (op->evaluate_at_safepoint()) { SafepointSynchronize::begin(); // 进入安全点,阻塞所有线程 // ...执行GC等操作... SafepointSynchronize::end(); // 结束安全点,唤醒线程 } }

  • ​功能​​:执行需要安全点的 VM 操作(如 GC)。
  • ​关键点​​:
    • SafepointSynchronize::begin():暂停所有线程,进入安全点。
    • SafepointSynchronize::end():完成 GC 后,调用此函数解除线程阻塞。

​2. SafepointSynchronize::end() - 结束安全点​

 

cpp

复制

 

void SafepointSynchronize::end() { disarm_safepoint(); // 核心:解除安全点 Universe::heap()->safepoint_synchronize_end(); // GC后清理 }

  • ​功能​​:安全点结束时的清理工作。
  • ​核心调用​​:disarm_safepoint() 负责恢复线程运行。

​3. SafepointSynchronize::disarm_safepoint() - 解除安全点​

 

cpp

复制

 

void SafepointSynchronize::disarm_safepoint() { _state = _not_synchronized; // 全局状态标记为非同步 Atomic::store(&_safepoint_counter, _safepoint_counter + 1); // 递增安全点ID // 恢复所有线程状态 for (JavaThread *current : JavaThreadIterator()) { current->safepoint_state()->restart(); // 标记线程为运行状态 } _wait_barrier->disarm(); // 唤醒阻塞的线程 Threads_lock->unlock(); // 解锁线程列表 }

  • ​功能​​:
    • 将全局安全点状态设置为 ​​非同步​​。
    • 更新安全点计数器,触发内存屏障保证可见性。
    • 遍历所有线程,调用 restart() 重置线程状态。
    • 调用屏障的 disarm() 方法唤醒所有线程。

​4. LinuxWaitBarrier::disarm() - 唤醒线程​

 

cpp

复制

 

void LinuxWaitBarrier::disarm() { _futex_barrier = 0; // 重置屏障值 syscall(SYS_futex, &_futex_barrier, FUTEX_WAKE_PRIVATE, INT_MAX); // 唤醒所有等待线程 }

  • ​功能​​:通过 Linux 的 futex 系统调用唤醒所有阻塞在安全点的线程。
  • ​关键点​​:
    • FUTEX_WAKE_PRIVATE:唤醒所有在 _futex_barrier 上等待的线程。
    • INT_MAX:唤醒最大数量的线程(实际唤醒所有等待的线程)。

​5. 线程阻塞与唤醒机制​

  • ​线程阻塞​​:
    • 在安全点开始时,线程通过 SafepointSynchronize::block() 调用 futex 的 FUTEX_WAIT 进入阻塞状态。
     

    cpp

    复制

     

    void SafepointSynchronize::block(JavaThread* thread) { _wait_barrier->wait(active_safepoint_id); // FUTEX_WAIT }

  • ​线程唤醒​​:
    • GC 完成后,disarm_safepoint() 调用 LinuxWaitBarrier::disarm(),通过 FUTEX_WAKE 唤醒所有阻塞线程。

​总结​

  1. ​安全点进入​​:GC 开始时,所有线程通过 futex 进入阻塞状态。
  2. ​GC 执行​​:VM 线程在安全点内执行垃圾回收。
  3. ​安全点退出​​:
    • 更新全局状态和计数器。
    • 重置每个线程的运行状态。
    • 调用 futex 的 FUTEX_WAKE 唤醒所有线程。
  4. ​线程恢复​​:被唤醒的线程继续执行后续代码。

这些代码是 ​​垃圾回收完成后解除线程阻塞的核心实现​​,通过操作系统提供的 futex 机制高效地管理线程的阻塞与唤醒。

 ##源码

void VMThread::inner_execute(VM_Operation* op) {
  assert(Thread::current()->is_VM_thread(), "Must be the VM thread");

  VM_Operation* prev_vm_operation = NULL;
  if (_cur_vm_operation != NULL) {
    // Check that the VM operation allows nested VM operation.
    // This is normally not the case, e.g., the compiler
    // does not allow nested scavenges or compiles.
    if (!_cur_vm_operation->allow_nested_vm_operations()) {
      fatal("Unexpected nested VM operation %s requested by operation %s",
            op->name(), _cur_vm_operation->name());
    }
    op->set_calling_thread(_cur_vm_operation->calling_thread());
    prev_vm_operation = _cur_vm_operation;
  }

  _cur_vm_operation = op;

  HandleMark hm(VMThread::vm_thread());
  EventMarkVMOperation em("Executing %sVM operation: %s", prev_vm_operation != NULL ? "nested " : "", op->name());

  log_debug(vmthread)("Evaluating %s %s VM operation: %s",
                       prev_vm_operation != NULL ? "nested" : "",
                      _cur_vm_operation->evaluate_at_safepoint() ? "safepoint" : "non-safepoint",
                      _cur_vm_operation->name());

  bool end_safepoint = false;
  if (_cur_vm_operation->evaluate_at_safepoint() &&
      !SafepointSynchronize::is_at_safepoint()) {
    SafepointSynchronize::begin();
    if (_timeout_task != NULL) {
      _timeout_task->arm();
    }
    end_safepoint = true;
  }

  evaluate_operation(_cur_vm_operation);

  if (end_safepoint) {
    if (_timeout_task != NULL) {
      _timeout_task->disarm();
    }
    SafepointSynchronize::end();
  }

  _cur_vm_operation = prev_vm_operation;
}

// Wake up all threads, so they are ready to resume execution after the safepoint
// operation has been carried out
void SafepointSynchronize::end() {
  assert(Threads_lock->owned_by_self(), "must hold Threads_lock");
  EventSafepointEnd event;
  assert(Thread::current()->is_VM_thread(), "Only VM thread can execute a safepoint");

  disarm_safepoint();

  Universe::heap()->safepoint_synchronize_end();

  SafepointTracing::end();

  post_safepoint_end_event(event, safepoint_id());
}


void SafepointSynchronize::disarm_safepoint() {
  uint64_t active_safepoint_counter = _safepoint_counter;
  {
    JavaThreadIteratorWithHandle jtiwh;
#ifdef ASSERT
    // A pending_exception cannot be installed during a safepoint.  The threads
    // may install an async exception after they come back from a safepoint into
    // pending_exception after they unblock.  But that should happen later.
    for (; JavaThread *cur = jtiwh.next(); ) {
      assert (!(cur->has_pending_exception() &&
                cur->safepoint_state()->is_at_poll_safepoint()),
              "safepoint installed a pending exception");
    }
#endif // ASSERT

    OrderAccess::fence(); // keep read and write of _state from floating up
    assert(_state == _synchronized, "must be synchronized before ending safepoint synchronization");

    // Change state first to _not_synchronized.
    // No threads should see _synchronized when running.
    _state = _not_synchronized;

    // Set the next dormant (even) safepoint id.
    assert((_safepoint_counter & 0x1) == 1, "must be odd");
    Atomic::release_store(&_safepoint_counter, _safepoint_counter + 1);

    OrderAccess::fence(); // Keep the local state from floating up.

    jtiwh.rewind();
    for (; JavaThread *current = jtiwh.next(); ) {
      // Clear the visited flag to ensure that the critical counts are collected properly.
      DEBUG_ONLY(current->reset_visited_for_critical_count(active_safepoint_counter);)
      ThreadSafepointState* cur_state = current->safepoint_state();
      assert(!cur_state->is_running(), "Thread not suspended at safepoint");
      cur_state->restart(); // TSS _running
      assert(cur_state->is_running(), "safepoint state has not been reset");
    }
  } // ~JavaThreadIteratorWithHandle

  // Release threads lock, so threads can be created/destroyed again.
  Threads_lock->unlock();

  // Wake threads after local state is correctly set.
  _wait_barrier->disarm();
}

// Guarantees any thread that called wait() will be awake when it returns.
  // Provides a trailing fence.
  void disarm() {
    assert(_owner == Thread::current(), "Not owner thread");
    _impl.disarm();
  }

// Guarantees any thread that called wait() will be awake when it returns.
  // Provides a trailing fence.
  void disarm() {
    assert(_owner == Thread::current(), "Not owner thread");
    _impl.disarm();
  }

void LinuxWaitBarrier::disarm() {
  assert(_futex_barrier != 0, "Should be armed/non-zero.");
  _futex_barrier = 0;
  int s = futex(&_futex_barrier,
                FUTEX_WAKE_PRIVATE,
                INT_MAX /* wake a max of this many threads */);
  guarantee_with_errno(s > -1, "futex FUTEX_WAKE failed");
}

static int futex(volatile int *addr, int futex_op, int op_arg) {
  return syscall(SYS_futex, addr, futex_op, op_arg, NULL, NULL, 0);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2378620.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux笔记】nfs网络文件系统与autofs(nfsdata、autofs、autofs.conf、auto.master)

一、nfs概念 NFS(Network File System,网络文件系统) 是一种由 Sun Microsystems 于1984年开发的分布式文件系统协议,允许用户通过网络访问远程计算机上的文件,就像访问本地文件一样。它广泛应用于 Unix/Linux 系统&a…

博客打卡-求解流水线调度

题目如下: 有n个作业(编号为1~n)要在由两台机器M1和M2组成的流水线上完成加工。每个作业加工的顺序都是先在M1上加工,然后在M2上加工。M1和M2加工作业i所需的时间分别为ai和bi(1≤i≤n)。 流水…

数据库blog1_信息(数据)的处理与效率提升

🌿信息的处理 🍂实际中离不开信息处理 ● 解决问题的建模 任何对问题的处理都可以看作数据的输入、处理、输出。 eg.一个项目中,用户点击信息由前端接收传递到后端处理后返回结果eg.面对一个问题,我们在搜集信息后做出处理与分析…

布隆过滤器介绍及其在大数据场景的应用

目录 布隆过滤器(Bloom Filter)介绍一、布隆过滤器的基本原理插入元素过程:查询元素过程: 二、布隆过滤器的特点三、误判率计算四、举例说明五、总结 Python版的简单布隆过滤器实现示例一、简单布隆过滤器Python示例二、布隆过滤器…

Fidder基本操作

1.抓取https请求 Fidder默认不能抓取https请求,我们必须通过相应的设置才能抓取https请求 1.选择tools下的option 2.选择https选项,并且勾选下面的选项 3.点击Actions导出信任证书到桌面(expert root certificate to desktop) 4.在浏览器中添加对应的证…

项目管理进阶:精读 78页华为项目管理高级培训教材【附全文阅读】

本文概述了华为项目管理(高级)课程的学习目标及学习方法。学习该课程后,学员应能: 1. **深刻理解项目管理**:掌握项目管理的基本概念与方法,构建项目管理思维框架。 2. **应用IBEST理念**:结合I…

[Java] 方法和数组

目录 1. 方法 1.2 什么是方法 1.2 方法的定义 1.3 方法的调用 1.4 方法的重载 1.5 递归 2. 一维数组 2.1 什么是数组 2.2 数组的创建 2.3 数组的初始化 2.4 遍历数组 2.5 引用数据类型 2.6 关于null 2.7 数组转字符串 2.8 数组元素的查找 2.9 数组的排序 2.10…

微软家各种copilot的AI产品:Github copilot、Microsoft copilot

背景 大家可能听到很多copilot,比如 Github Copilot,Microsoft Copilot、Microsoft 365 Copilot,有什么区别 Github Copilot:有网页版、有插件(idea、vscode等的插件),都是面向于程序员的。Mi…

回溯法理论基础 LeetCode 77. 组合 LeetCode 216.组合总和III LeetCode 17.电话号码的字母组合

目录 回溯法理论基础 回溯法 回溯法的效率 用回溯法解决的问题 如何理解回溯法 回溯法模板 LeetCode 77. 组合 回溯算法的剪枝操作 LeetCode 216.组合总和III LeetCode 17.电话号码的字母组合 回溯法理论基础 回溯法 回溯法也可以叫做回溯搜索法,它是一…

【进程控制二】进程替换和bash解释器

【进程控制二】进程替换 1.exec系列接口2.execl系列2.1execl接口2.2execlp接口2.3execle 3.execv系列3.1execv3.2总结 4.实现一个bash解释器4.1内建命令 通过fork创建的子进程,会继承父进程的代码和数据,因此本质上还是在执行父进程的代码 进程替换可以将…

JavaScript 的编译与执行原理

文章目录 前言🧠 一、JavaScript 编译与执行过程1. 编译阶段(发生在代码执行前)✅ 1.1 词法分析(Lexical Analysis)✅ 1.2 语法分析(Parsing)✅ 1.3 语义分析与生成执行上下文 🧰 二…

NHANES指标推荐:FMI

文章题目:Exploring the relationship between fat mass index and metabolic syndrome among cancer patients in the U.S: An NHANES analysis DOI:10.1038/s41598-025-90792-9 中文标题:探索美国癌症患者脂肪量指数与代谢综合征之间的关系…

【JDBC】JDBC常见错误处理方法及驱动的加载

MySQL8中数据库连接的四个参数有两个发生了变化 String driver "com.mysql.cj.jdbc.Driver"; String url "jdbc:mysql://127.0.0.1:3306/mydb?useSSLfalse&useUnicodetrue&characterEncodingutf8&serverTimezoneAsia/Shanghai"; 或者Strin…

车载以太网驱动智能化:域控架构设计与开发实践

title: 车载以太网驱动专用车智能化:域控架构设计与开发实践 date: 2023-12-01 categories: 新能源汽车 tags: [车载以太网, 电子电气架构, 域控架构, 专用车智能化, SOME/IP, AUTOSAR] 引言:专用车智能化转型的挑战与机遇 专用车作为城市建设与工业运输…

如何利用技术手段提升小学数学练习效率

在日常辅导孩子数学作业的过程中,我发现了一款比较实用的练习题生成工具。这个工具的安装包仅1.8MB大小,但基本能满足小学阶段的数学练习需求。 主要功能特点: 参数化出题 可自由设置数字范围(如10以内、100以内) 支…

BGP路由策略 基础实验

要求: 1.使用Preva1策略,确保R4通过R2到达192.168.10.0/24 2.用AS_Path策略,确保R4通过R3到达192.168.11.0/24 3.配置MED策略,确保R4通过R3到达192.168.12.0/24 4.使用Local Preference策略,确保R1通过R2到达192.168.1.0/24 …

第9讲、深入理解Scaled Dot-Product Attention

Scaled Dot-Product Attention是Transformer架构的核心组件,也是现代深度学习中最重要的注意力机制之一。本文将从原理、实现和应用三个方面深入剖析这一机制。 1. 基本原理 Scaled Dot-Product Attention的本质是一种加权求和机制,通过计算查询(Query…

双向长短期记忆网络-BiLSTM

5月14日复盘 二、BiLSTM 1. 概述 双向长短期记忆网络(Bi-directional Long Short-Term Memory,BiLSTM)是一种扩展自长短期记忆网络(LSTM)的结构,旨在解决传统 LSTM 模型只能考虑到过去信息的问题。BiLST…

MySQL UPDATE 执行流程全解析

引言 当你在 MySQL 中执行一条 UPDATE 语句时,背后隐藏着一套精密的协作机制。从解析器到存储引擎,从锁管理到 WAL 日志,每个环节都直接影响数据一致性和性能。 本文将通过 Mermaid 流程图 和 时序图,完整还原 UPDATE 语句的执行…

亚马逊云科技:开启数字化转型的无限可能

在数字技术蓬勃发展的今天,云计算早已突破单纯技术工具的范畴,成为驱动企业创新、引领行业变革的核心力量。亚马逊云科技凭借前瞻性的战略布局与持续的技术深耕,在全球云计算领域树立起行业标杆,为企业和个人用户提供全方位、高品…