jvm安全點(三)openjdk17 c++源碼垃圾回收之安全點結束,喚醒線程

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 // ASSERTOrderAccess::fence(); // keep read and write of _state from floating upassert(_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 _runningassert(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.pswp.cn/news/906018.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/906018.shtml
英文地址,請注明出處:http://en.pswp.cn/news/906018.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

102. 二叉樹的層序遍歷遞歸法:深度優先搜索的巧妙應用

二叉樹的層序遍歷是一種經典的遍歷方式,它要求按層級逐層訪問二叉樹的節點。通常我們會使用隊列來實現層序遍歷,但遞歸法也是一種可行且有趣的思路。本文將深入探討遞歸法解決二叉樹層序遍歷的核心難點,并結合代碼和模擬過程進行詳細講解。 …

首個窗口級無人機配送VLN系統!中科院LogisticsVLN:基于MLLM實現精準投遞

導讀 隨著智能物流需求日益增長,特別是“最后一公里”配送場景的精細化,傳統地面機器人逐漸暴露出適應性差、精度不足等瓶頸。為此,本文提出了LogisticsVLN系統——一個基于多模態大語言模型的無人機視覺語言導航框架,專為窗戶級別…

WPF Datagrid 數據加載和性能

這篇文章并非討論 WPF Datagrid 的性能數據,而只是簡單介紹一下為了使其性能良好,你需要注意哪些方面。我不太想使用性能分析器來展示實際數據,而是盡可能地使用了 Stopwatch 類。這篇文章不會深入探討處理海量數據的技術,例如分頁…

matlab求矩陣的逆、行列式、秩、轉置

inv - 計算矩陣的逆 用途:計算一個可逆矩陣的逆矩陣。 D [1, 2; 3, 4]; % 定義一個2x2矩陣 D_inv inv(D); % 計算矩陣D的逆 disp(D_inv);det - 計算矩陣的行列式 用途:計算方陣的行列式。 E [1, 2; 3, 4]; determinant det(E); % 計算行列式 disp…

ridecore流水線解讀

文章目錄 流水線stage分屬前后端PCpipelineIFIDDPDP 與 SW 中間沒有latchSWCOM 源碼地址 流水線stage分屬前后端 IF -> ID -> DP -> SW -> EX -> COM分類階段說明前端IF指令獲取階段。PC 使用分支預測器,訪問指令存儲器。典型前端操作。前端ID解碼并…

【SpringBoot】關于MP使用中配置了數據庫表前綴的問題

problem 使用MP時,在application.yml配置文件中配置了MP匹配數據庫表中的表名時的前綴作了規定,如下: 那么當我運行時報錯了錯誤,報錯信息如下: 因為我數據庫表的書類表名是book,MP在匹配時使用了表名前…

印度Rummy游戲支付通道申請策略:技巧類游戲的合規與創新

本文為印度支付申請科普文,自去年開始,印度Rummy類游戲申請印度支付都需要擁有AIGF的會員及產品證書。 如需要rummy可以通過AIGF審核的源。碼,或咨詢AIGF的相關內容,可以聯。系老妙。 印度作為全球棋牌類游戲增長最快的市場之一&…

日志與策略模式

什么是設計模式 IT?業 ,為了讓 菜雞們不太拖?佬的后腿, 于是?佬們針對?些經典的常?的場景, 給定了?些對應的解決?案, 這個就是 設計模式 日志認識 計算機中的?志是記錄系統和軟件運?中發?事件的?件,主要作?是監控運?狀態、記錄異常信 息&#xff…

解鎖Ubuntu高效部署!自動安裝配置文件YAML全解析

我們之前介紹了兩種Ubuntu系統的安裝方式,分別對應桌面版(準備搞OpenStack了,先裝一臺最新的Ubuntu 23.10)和服務器版(Ubuntu 22.04 LTS服務器版本安裝演示)。但對于有些用戶,因為技術問題&…

關系代數和關系數據庫語言(SQL)

閱讀提示:本篇文章較長,建議從目錄上選取想看的內容。代碼上的話,我習慣用小寫,如果看不習慣建議跳過。有問題歡迎討論!!! 一、基礎概念 1.1數據庫的概念 數據庫(Database)是按照數據結構來組…

EXO 可以將 Mac M4 和 Mac Air 連接起來,并通過 Ollama 運行 DeepSeek 模型

EXO 可以將 Mac M4 和 Mac Air 連接起來,并通過 Ollama 運行 DeepSeek 模型。以下是具體實現方法: 1. EXO 的分布式計算能力 EXO 是一個支持 分布式 AI 計算 的開源框架,能夠將多臺 Mac 設備(如 M4 和 Mac Air)組合成…

區塊鏈基本理解

文章目錄 前言一、什么是分布式賬本(DLT)二、什么是P2P網絡?二、共識算法三、密碼算法前言 區塊鏈是由一個一個數據塊組成的鏈條,按照時間順序將數據塊逐一鏈接,通過哈希指針鏈接,所有的數據塊共同維護一份分布式賬本(DLT),每個節點(可以理解為一個玩家,一臺計算機)都擁…

Node.js中的洋蔥模型

文章目錄 前言 前言 Node.js中的洋蔥模型是一種中間件執行機制,主要用于處理HTTP請求和響應的流程控制。該模型通過層層包裹的中間件結構,實現請求從外到內穿透、響應從內向外返回的順序執行。以下從核心概念、實現原理、框架差異及實際應用等方面解析&…

UI-TARS Desktop:用自然語言操控電腦,AI 重新定義人機交互

在人工智能技術飛速發展的今天,從文本生成到圖像識別,AI 的能力邊界不斷被打破。而字節跳動近期開源的 UI-TARS Desktop,則將這一技術推向了更復雜的交互場景——通過自然語言直接控制計算機界面,實現了圖形用戶界面(GUI)的智能化自動化。這款工具不僅降低了操作門檻,更…

一個可拖拉實現列表排序的WPF開源控件

從零學習構建一個完整的系統 推薦一個可通過拖拉,來實現列表元素的排序的WPF控件。 項目簡介 gong-wpf-dragdrop是一個開源的.NET項目,用于在WPF應用程序中實現拖放功能,可以讓開發人員快速、簡單的實現拖放的操作功能。 可以在同一控件內…

C語言中字符串函數的詳細講解

C語言提供了豐富的字符串處理函數&#xff0c;這些函數在<string.h>頭文件中聲明。以下是一些常用字符串函數的詳細講解&#xff1a; 字符串拷貝函數 strcpy 功能&#xff1a;將源字符串&#xff08;包括結尾的\0&#xff09;復制到目標字符串。原型&#xff1a;char *s…

可視化數據圖表怎么做?如何實現三維數據可視化?

目錄 一、三維數據可視化的要點 1. 明確數據可視化的目標 2. 篩選與整理數據 3. 選擇合適的圖表類型 4. 運用專業工具制作 5. 優化圖表的展示效果 二、數據可視化圖表怎么做&#xff1f; 1. 理解三維數據的特性 2. 數據處理與三維建模 3. 設置光照與材質效果 4. 添加…

在Linux服務器上部署Jupyter Notebook并實現ssh無密碼遠程訪問

Jupyter notebook版本7.4.2&#xff08;這個版本AI提示我Jupyter7&#xff08;底層是 jupyter_server 2.x&#xff09; 服務器開啟服務 安裝Jupyter notebook 7.4.2成功后&#xff0c;終端輸入 jupyter notebook --generate-config 這將在 ~/.jupyter/ 目錄下生成 jupyter_…

走出 Demo,走向現實:DeepSeek-VL 的多模態工程路線圖

目錄 一、引言&#xff1a;多模態模型的關鍵轉折點 &#xff08;一&#xff09;當前 LMM 的三個關鍵挑戰 1. 數據的真實性不足 2. 模型設計缺乏場景感知 3. 語言能力與視覺能力難以兼顧 &#xff08;二&#xff09;DeepSeek-VL 的根本出發點&#xff1a;以真實任務為錨點…

數據庫原理及其應用 第六次作業

題目 參考答案 題目1. 教材P148第1題 問題&#xff1a;什么是數據庫的安全性&#xff1f; 答案&#xff1a;數據庫的安全性是指保護數據庫以防止不合法的使用所造成的數據泄露、更改或破壞 。它通過用戶身份鑒別、存取控制&#xff08;包括自主存取控制和強制存取控制&#x…