深入解析線程上下文切換的原理與優化策略

深入解析線程上下文切換的原理與優化策略

  • 定義
  • 觸發條件
  • 線程上下文切換的過程
  • 線程上下文切換的開銷
  • 減少上下文切換的方法
  • 示例代碼
  • 總結

線程上下文切換(Thread Context Switch)是操作系統調度機制的重要組成部分。它涉及保存當前線程的狀態并恢復新線程的狀態,使得CPU能夠在多個線程之間共享執行時間。理解其工作原理和涉及的源碼有助于優化多線程程序的性能。以下是對線程上下文切換的詳細解釋及相關源碼分析。

定義

線程上下文切換(Thread Context Switch)是指操作系統將 CPU 從一個線程切換到另一個線程的過程。在這個過程中,操作系統需要保存當前線程的狀態(如寄存器、程序計數器等),并恢復另一個線程的狀態。

觸發條件

線程上下文切換可以由以下幾種情況觸發:

  • 時間片到期:現代操作系統通常使用時間片輪轉調度算法(round-robin scheduling),每個線程分配一個時間片,當時間片用盡時,操作系統會進行上下文切換。
  • I/O 操作:當一個線程等待I/O操作完成時,操作系統會將該線程阻塞,并切換到另一個可運行的線程。
  • 優先級調度:如果有更高優先級的線程變為可運行狀態,操作系統可能會立即進行上下文切換。
  • 系統調用:某些系統調用(如sleep、yield等)可能會導致上下文切換。
  • 鎖競爭:當一個線程嘗試獲取一個已經被其他線程持有的鎖時,可能會被阻塞,從而觸發上下文切換。

線程上下文切換的過程

線程上下文切換涉及以下步驟:

a. 保存當前線程狀態

操作系統首先保存當前線程的CPU寄存器狀態,包括程序計數器(PC)、棧指針(SP)、通用寄存器等。此外,還會保存線程的內核棧和處理器狀態字(PSW)。

b. 更新線程控制塊(TCB)

操作系統更新當前線程的線程控制塊(Thread Control Block, TCB),將其狀態設置為“就緒”或“阻塞”。

c. 選擇下一個線程

調度器(Scheduler)根據調度算法選擇下一個要運行的線程,并將其TCB狀態設置為“運行中”。

d. 恢復下一個線程狀態
操作系統恢復即將運行的線程的寄存器狀態、程序計數器和棧指針等信息。最終,CPU開始執行新線程的指令。

線程上下文切換的開銷

線程上下文切換是有成本的,主要體現在以下幾個方面:

  • CPU開銷:保存和恢復線程狀態需要CPU執行額外的指令。
  • 緩存失效:上下文切換可能導致CPU緩存、TLB(Translation Lookaside Buffer)和分支預測器的失效,從而增加內存訪問延遲。
  • 內核態開銷:上下文切換通常涉及從用戶態切換到內核態的操作,這進一步增加了開銷。

減少上下文切換的方法

  • 減少線程數量:使用合理數量的線程,避免線程過多導致頻繁切換。
  • 無鎖編程:減少線程之間的鎖競爭,降低阻塞幾率。
  • 使用適當的線程池:利用線程池復用線程,避免頻繁的線程創建和銷毀。
  • 線程池復用:選擇合適的調度策略,減少不必要的上下文切換。

示例代碼

以下是一個Java示例,演示了線程的簡單切換:

public class ContextSwitchDemo {public static void main(String[] args) {Runnable task1 = () -> {for (int i = 0; i < 5; i++) {System.out.println("Task 1 - Count: " + i);try {Thread.sleep(100); // 模擬任務執行} catch (InterruptedException e) {e.printStackTrace();}}};Runnable task2 = () -> {for (int i = 0; i < 5; i++) {System.out.println("Task 2 - Count: " + i);try {Thread.sleep(100); // 模擬任務執行} catch (InterruptedException e) {e.printStackTrace();}}};Thread thread1 = new Thread(task1);Thread thread2 = new Thread(task2);thread1.start();thread2.start();}
}

在這個示例中,task1和task2兩個任務分別由thread1和thread2執行。由于使用了Thread.sleep(100),操作系統會進行上下文切換,將CPU從一個線程切換到另一個線程。

操作系統層面的上下文切換源碼
以下是Linux內核中上下文切換的部分代碼(以switch_to宏為例):

#define switch_to(prev, next, last)                    \
do {                                    \asm volatile("pushfl\n\t" /* save flags */        \"pushl %%ebp\n\t" /* save EBP */        \"movl %%esp,%[prev_sp]\n\t" /* save ESP */    \"movl %[next_sp],%%esp\n\t" /* restore ESP */    \"movl $1f,%[prev_ip]\n\t" /* save EIP */    \"pushl %[next_ip]\n\t" /* restore EIP */    \"jmp __switch_to\n" /* call switch function */    \"1:\t" /* next comes here */            \"popl %%ebp\n\t" /* restore EBP */        \"popfl\n" /* restore flags */            \: [prev_sp] "=m" (prev->thread.sp),        \[prev_ip] "=m" (prev->thread.ip)        \: [next_sp] "m" (next->thread.sp),        \[next_ip] "m" (next->thread.ip)        \: "memory");                    \
} while (0)

這個宏定義了上下文切換的核心步驟,涉及保存和恢復CPU寄存器、程序計數器和堆棧指針等操作。

總結

線程上下文切換是操作系統多線程調度中的一個關鍵機制。雖然它有助于實現并發執行,但頻繁的上下文切換會帶來性能開銷。通過理解其原理,并應用適當的優化方法,可以有效減少上下文切換的開銷,提升多線程應用的性能。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/14460.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/14460.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/14460.shtml

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

相關文章

vue中使用ant的rangePicker設置禁選時間和時間格式

<a-range-pickerstyle"width: 100%":disabled-date"disabledDate"v-model:value"time"valueFormat"YYYY-MM-DD" />valueFormat設置時間格式YYYY-MM-DD 通過dayjs獲取時間&#xff0c;return過濾后的時間 const disabledDate (…

安裝apex時遇到的問題

Apex是混合精度庫&#xff0c;安裝過程中常常出現各種問題&#xff0c;在此記錄一下 首先&#xff0c;不能使用pip install apex,這是兩個完全不同的庫&#xff0c;需要去官網下載 其次&#xff0c;參考官網安裝時可能會報錯&#xff1a;could not build wheels for apex, whic…

C/C++運行時庫和UCRT系統通用運行時庫總結及問題實例分享

目錄 1、概述 2、不同版本的Visual Studio對應的運行時庫說明 3、在Windbg10.0安裝目錄中獲取UCRT通用運行時庫 4、微軟官網對UCRT通用運行時庫的相關說明 5、使用Visual Studio 2017開發軟件初期遇到的UCRT通用運行時庫問題 6、如何查看軟件依賴了哪些C/C運行時庫&#…

后端雪花算法主鍵ID傳到前端變了

Mybatis Plus 的主鍵策略&#xff1a; /*** id*/TableId(type IdType.ASSIGN_ID)private Long id; 這個主鍵策略會用雪花算法生成一個 19位的ID&#xff0c;比如 1791006670084734978 現象 后端生成的 id 是正常的&#xff0c;通過 swagger 文檔此時獲取到的 id 也和數據庫中…

leetcode-盛水最多的容器-109

題目要求 思路 1.正常用雙循環外循環i從0開始&#xff0c;內循環從height.size()-1開始去計算每一個值是可以的&#xff0c;但是因為數據量太大&#xff0c;會超時。 2.考慮到超時&#xff0c;需要優化一些&#xff0c;比如第一個選下標1&#xff0c;第二個選下標3和第一個選下…

Java 面試題日常練習

### 基礎知識 1. **什么是 JVM&#xff1f;解釋其架構。** - JVM&#xff08;Java Virtual Machine&#xff09;是 Java 程序的運行時環境。其架構包括類加載器子系統、運行時數據區&#xff08;堆、棧、本地方法棧、PC 寄存器、方法區&#xff09;、執行引擎和本地方法接口…

心識宇宙 x TapData:如何加速落地實時數倉,助力 AI 企業智慧決策

使用 TapData&#xff0c;化繁為簡&#xff0c;擺脫手動搭建、維護數據管道的諸多煩擾&#xff0c;輕量代替 OGG、DSG 等同步工具&#xff0c;「CDC 流處理 數據集成」組合拳&#xff0c;加速倉內數據流轉&#xff0c;幫助企業將真正具有業務價值的數據作用到實處&#xff0c…

基于springboot實現華府便利店信息管理系統項目【項目源碼+論文說明】計算機畢業設計

基于springboot實現華府便利店信息管理系統演示 摘要 現代經濟快節奏發展以及不斷完善升級的信息化技術&#xff0c;讓傳統數據信息的管理升級為軟件存儲&#xff0c;歸納&#xff0c;集中處理數據信息的管理方式。本華府便利店信息管理系統就是在這樣的大環境下誕生&#xff…

電影《朝云暮雨》觀后感

上周看了電影《朝云暮雨》&#xff0c;看完之后&#xff0c;感覺自己整個人都不太好了&#xff0c;也不是說電影太差&#xff0c;只是覺得電影沒有傳達正能量&#xff0c;讓人很不舒服。 &#xff08;1&#xff09;演技在線 對于著名的演員“范偉”&#xff0c;或者說&#x…

Payload SDK dji

開發硬件 感謝您的耐心等待&#xff0c;建議您可以考慮下樹莓派4B或Jetson Nano開發板&#xff0c;看您需求選擇&#xff0c;OSDK即將停止服務&#xff0c;我們建議您使用PSDK來進行開發&#xff0c;PSDK包含了OSDK的功能。Payload SDK 感謝您對大疆產品的支持&#xff01;祝…

【耕地保衛戰:揭秘“占補平衡”】守護糧倉的智慧策略

嗨&#xff0c;各位小伙伴們&#xff0c;今天咱們來聊聊一個與我們每日餐桌緊密相關的主題——耕地占補平衡。在現代化的車輪滾滾向前時&#xff0c;如何在發展與保護之間找到那個微妙的平衡點&#xff0c;確保我們的“米袋子”滿滿當當呢&#xff1f;這就不得不提到耕地占補平…

SpringSession原理簡析

本文借鑒于&#xff1a;Spring-Session 原理簡析 - 知乎 (zhihu.com) 目錄 概述 使用方式 原理 總結 概述 Session的原理 Session是存在服務器的一種用來存放用戶數據的類哈希表結構&#xff0c;當瀏覽器第一次發送請求的時候服務器會生成一個hashtable和一個sessionid&…

論文閱讀--Language-driven Semantic Segmentation

效果很好&#xff0c;文本增加一個詞&#xff0c;就能找到對應的分割地方&#xff0c;給出的無用標簽也不會去錯誤分割&#xff0c;而且能理解文本意思&#xff0c;例如dog和pet都能把狗給分割出來 image encoder使用DPT分割模型&#xff0c;大致架構為ViTdecoder&#xff0c;d…

【個人經歷分享】末流本科地信,畢業轉碼經驗

本人24屆末流本科&#xff0c;地理信息科學專業。 我們這個專業可以說是 “高不成&#xff0c;低不就”的專業&#xff0c;什么都學但都不精。考研我實在是卷不動同學歷的人&#xff0c;我在大三的時候就開始考慮轉碼。 至于我為什么選擇轉碼&#xff0c;選擇了GIS開發&#xf…

element ui 下拉框Select 選擇器 上下箭頭旋轉方向樣式錯亂——>優化方案

目錄 前言1、問題復現2、預期效果3、input框樣式修改解析4、修改方案 &#x1f680;寫在最后 前言 測試A&#xff1a;那啥&#xff01;摳圖仔&#xff0c;樣式怎么點著點著就出問題了。 前端&#xff1a;啥&#xff1f;css樣式錯亂了&#xff1f;你是不是有緩存啊&#xff01…

js常用數組方法

1.arr.push() -末尾添加 該方法可以向數組末尾添加一個或多個元素&#xff0c;并返回數組新的長度可以將要添加的元素作為方法的參數傳遞&#xff0c;這樣這些元素將會自動添加到元素的末尾原數組會發生變化 var arr [ 1, 2, 3, 4 ] arr.push(5) console.log(arr) // [ 1, …

linux命令arp的使用

arp arp 命令用于顯示和修改 IP 到 MAC 轉換表 補充說明 arp 命令 是 Address Resolution Protocol&#xff0c;地址解析協議&#xff0c;是通過解析網絡層地址來找尋數據鏈路層地址的一個網絡協議包中極其重要的網絡傳輸協議。而該命令可以顯示和修改 arp 協議解析表中的緩…

Mia for Gmail for Mac:Mac用戶的郵件管理首選

對于追求高效工作的Mac用戶來說&#xff0c;Mia for Gmail for Mac無疑是郵件管理的首選工具。它以其卓越的性能和豐富的功能&#xff0c;為用戶帶來了前所未有的高效郵件管理體驗。 Mia for Gmail for Mac不僅支持多帳號登錄和標簽選擇功能&#xff0c;還提供了郵件分類、垃圾…

linux 中 fd 申請和釋放管理(兩級 bitmap)

linux 中 fd 的幾點理解_linux fd-CSDN博客 通過上邊的文章&#xff0c;我們可以知道&#xff0c;在 linux 中&#xff0c;fd 有以下幾點需要了解&#xff1a; &#xff08;1&#xff09;fd 表示進程打開的文件&#xff0c;是進程級別的資源&#xff0c;不是系統級別的資源 …

【前端每日一題】day11

一個盒子(DIV)里有若干個小盒子&#xff0c;每個小盒子里還可能有多個小盒子 多層盒子結構。每個盒子都有一個唯一的id和 name 屬性。現在給出一個盒子的 id 請找到這個盒子并打開&#xff0c;輸出這個盒子內部所有小盒子的id和 name&#xff0c;并繼續打開這些小盒子輸出id和 …