25.線程概念和控制(二)

一、線程周邊問題

1.線程的優點

  • 創建一個新線程的代價要比創建一個新進程小得多。
  • 線程占用的資源要比進程少很多。
  • 能充分利用多處理器的可并行數量。
  • 在等待慢速I/O操作結束的同時,程序可執行其他的計算任務。
  • 計算密集型應用,為了能在多處理器系統上運行,將計算分解到多個線程中實現。
  • I/O密集型應用,為了提高性能,將I/O操作重疊。線程可以同時等待不同的I/O操作。

核心:

與進程之間的切換相比,線程之間的切換需要操作系統做的工作要少很多:
????????最主要的區別是線程的切換虛擬內存空間依然是相同的,但是進程切換是不同的。這兩種上下文切換的處理都是通過操作系統內核來完成的。內核的這種切換過程伴隨的最顯著的性能損耗是將寄存器中的內容切換出。
????????另外?個隱藏的損耗是上下文的切換會擾亂處理器的緩存機制。簡單的說,?旦去切換上下文,處理器中所有已經緩存的內存地址?瞬間都作廢了。還有?個顯著的區別是當你改變虛擬內存空間的時候,處理的頁表緩沖 TLB (快表)會被全部刷新,這將導致內存的訪問在?段時間內相當的低效。但是在線程的切換中,不會出現這個問題,當然還有硬件cache。

2.線程的缺點

性能損失
? ? ? ? 一個很少被外部事件阻塞的計算密集型線程往往無法與其它線程共享同?個處理器。如果計算密集型線程的數量比可用的處理器多,那么可能會有較大的性能損失,這里的性能損失指的是增加了額外的同步和調度開銷,而可用的資源不變。
健壯性降低
????????編寫多線程需要更全面更深入的考慮,在一個多線程程序里,因時間分配上的細微偏差或者因共享了不該共享的變量而造成不良影響的可能性是很大的,換句話說線程之間是缺乏保護的。
缺乏訪問控制
????????進程是訪問控制的基本粒度,在一個線程中調用某些OS函數會對整個進程造成影響。
編程難度提高
????????編寫與調試?個多線程程序比單線程程序困難得多。

3.進程和線程對比

進程是資源分配的基本單位。
線程是調度的基本單位。
線程共享進程數據,但也擁有自己的一部分數據:
????????線程ID
? ? ? ? 一組寄存器,線程的上下文數據(核心)
????????棧(核心)
????????errno
????????信號屏蔽字
????????調度優先級
棧說明線程有自己的入口函數,棧存放的是臨時變量,說明線程是一個動態的概念。
一組寄存器說明線程是被獨立調度的。
進程的多個線程共享:
????????同?地址空間,因此Text Segment、Data Segment都是共享的,如果定義?個函數,在各線程中都可以調用,如果定義一個全局變量,在各線程中都可以訪問到,除此之外,各線程還共享以下進程資源和環境:
? ? ? ? 文件描述符表
????????每種信號的處理方式(SIG_ IGN、SIG_ DFL或者自定義的信號處理函數)
????????當前工作目錄
? ? ? ? 用戶id和組id

二、線程控制

ps -aL可以用來查看用戶創建的線程。

task_struct

{

? ? ? ? pid_t pid;

? ? ? ? pid_t lwp;

}

light weight process:輕量級進程。CPU調度的時候,看lwp。

線程相關子問題:

1.關于調度的時間片問題:等分給不同的線程(防止線程無限分裂)

2.異常之后?任何一個線程崩潰,都會導致整個進程崩潰!

3.線程庫pthread是用戶層和操作系統層之間的一層中間層,在編譯時需要指定動態鏈接,帶上 -lpthread

????????Linux中,不存在真正意義上的線程,它所謂的概念,使用輕量級進程模擬的。在OS中,只有輕量級進程,所謂的線程,只是用戶層的概念。

????????但用戶層只認線程,因此pthread庫誕生了,把創建輕量級進程封裝起來,給用戶提供一批創建線程的接口。

?????????linux的線程實現,是在用戶層實現的。我們稱之為:用戶級線程。pthread為原生線程庫。

拓展:

linux創建輕量級進程的接口,vfork和clone創建子進程,和父進程共享地址空間。

C++11的多線程,在linux下,本質是封裝了pthread庫。

語言為了其跨平臺可移植性,其對應的線程實現都是封裝了各個操作系統的系統調用或對應的庫,通過條件編譯,形成庫。

int pthread_create(pthread_t *thread,? const pthread_attr_t *attr,

????????????????????????????????void *(*start_routine)(void *),? void *arg);

thread:線程id,輸出型參數(注:這個線程id是線程庫的概念,和lwp不同)

attr:線程屬性,設置稱nullptr

start_routine:新線程要執行的函數入口,一個函數指針

arg:新線程要執行的函數入口的參數

返回值:成功返回0,失敗返回錯誤數字。

注:線程創建好之后,新線程要被主線程等待->類似僵尸進程的問題,內存泄漏。

int pthread_join(pthread_t thread, void **retval);

thread:線程id

retval:返回值指針,輸出型參數

pthread_t pthread_self(void);? ? //獲取當前線程的id

為什么retval沒有信號部分的內容(沒有異常相關的內容)?

? ? 等待的目標線程,如果異常了,整個進程都退出了,包括main線程,所以,join異常,沒有意義,看也看不到!join都是基于:線程健康跑完的情況,不需要處理異常信號,異常信號,是進程要處理的話題!!!

POSIX線程庫
1.線程終止
1)線程的入口函數,進行return就是線程終止
注意:線程不能用exit終止,因為exit是終止進程的
2)pthread_exit()
3)如果線程被取消,退出結果是-1(PTHREAD_CANCLED)

pthread_exit函數
功能:線程終?
原型:
void pthread_exit(void *value_ptr);
參數:
value_ptr:value_ptr不要指向?個局部變量。
返回值:
無返回值,跟進程一樣,線程結束的時候無法返回到它的調用者(自身)
????????需要注意,pthread_exit或者return返回的指針所指向的內存單元必須是全局的或者是用malloc分配的, 不能在線程函數的棧上分配,因為當其它線程得到這個返回指針時線程函數已經退出了。
pthread_cancel函數
功能:取消?個執?中的線程
原型:
int pthread_cancel(pthread_t thread);
參數:
thread:線程ID
返回值:成功返回0;失敗返回錯誤碼
特別注意:取消的時候一定要保證新線程已經啟動。

2.線程分離

如果主線程不想再關心新線程,而是當新線程結束的時候,讓他自己釋放??
設置新線程為分離狀態

技術層面: ?線程默認是需要被等待的,joinable。如果不想讓主線程等待新線程
想讓新線程結束之后,自己退出,設置為分離狀態(!joinable or detach) ?// TODO
理解層面:線程分離,主分離新,新把自己分離。
分離的線程,依舊在進程的地址空間中,進程的所有資源,被分離的線程,依舊可以訪問,可以操作。主不等待新線程。
如果線程被設置為分離狀態,不需要進行join,join會失敗!!

#include <iostream>
#include <pthread.h>
#include <string>
#include <cstring>
#include <unistd.h>void *routine(void *args)
{std::string name = (char *)args;while (true){sleep(1);std::cout << "I am a thread, name: " << name << std::endl;}return (void *)123;
}int main()
{pthread_t tid;int n = pthread_create(&tid, nullptr, routine, (void *)"thread-1");// 分離新線程pthread_detach(tid);sleep(10);// 取消新線程pthread_cancel(tid);// 等待新線程,獲取返回值void *retval = nullptr;int ret = pthread_join(tid, &retval);if (ret != 0)std::cout << "等待失敗," << strerror(ret) << std::endl;elsestd::cout << "等待成功" << std::endl;while (true){std::cout << "當前是主線程,新線程已被回收,退出信息為:" << (long long int)retval << std::endl;sleep(1);}return 0;
}

三、線程ID及地址空間布局

????????Linux中沒有真正意義上的線程 -> OS不會直接提供線程的接口 -> 在用戶層,封裝輕量級進程,形成原生線程庫 -> 動態庫,ELF格式 -> 加載到內存和映射到進程地址空間。

????????線程的概念是在庫中維護的,在庫內部,一定會事先存在一個或多個被創建好的線程,如何管理這些線程?先描述,在組織。

struct tcb

{

? ? ? ? // 線程應有的屬性

? ? ? ? // 線程狀態

? ? ? ? // 線程ID

? ? ? ? // 線程獨立的棧結構

? ? ? ? // 線程棧大小

? ? ? ? ... ...

};

????????為什么不包括上下文,lwp,優先級?因為這是linux系統內核的具體實現,不是操作系統學科對于線程的描述,用戶不需要關心具體實現。

????????進程自己的代碼區可以訪問到pthread庫內部的函數和數據。

線程ID本質:管理線程塊的起始虛擬地址。

線程傳參和返回值:保存在線程管理塊中

線程分離:線程管理塊中存在標識位,標識線程是否分離。

以下是 glibc-2.4 pthread 源碼相關內容:
路徑: nptl/pthread_create.c

線程tcb結構屬性:

更正tid為lwp,輕量級進程的id。

創建線程create_thread

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

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

相關文章

【CVPR2023】奔跑而非行走:追求更高FLOPS以實現更快神經網絡

文章目錄一、論文信息二、論文概要三、實驗動機四、創新之處五、實驗分析六、核心代碼注釋版本七、實驗總結一、論文信息 論文題目&#xff1a;Run, Don’t Walk: Chasing Higher FLOPS for Faster Neural Networks中文題目&#xff1a;奔跑而非行走&#xff1a;追求更高FLOPS…

JVM(二)--- 類加載子系統

目錄 前言 一、類加載過程 1. loading階段 2. Linking階段 2.1 驗證 2.2 準備 2.3 解析 3. Initialization階段 二、類加載器 1. 類加載器的分類 2. 用戶自定義類加載器 三、雙親委派機制 四、其他知識點 前言 JVM的內存結構如圖所示&#xff1a; 一、類加載過程…

Docker 容器的使用

1.容器的基本信息[roothost1 ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9ac8245b5b08 img-layers-test "python /app/app.py" 45 hours ago Exited (0) 45 hour…

LLMs之Hallucinate:《Why Language Models Hallucinate》的翻譯與解讀

LLMs之Hallucinate&#xff1a;《Why Language Models Hallucinate》的翻譯與解讀 導讀&#xff1a;該論文深入分析了語言模型中幻覺現象的成因&#xff0c;認為幻覺源于預訓練階段的統計壓力和后訓練階段評估體系對猜測行為的獎勵。論文提出了通過修改評估方法&#xff0c;使其…

Spring Cloud @RefreshScope 作用是什么?

RefreshScope 是 Spring Cloud 中的一個重要注解&#xff0c;主要作用如下&#xff1a; 主要功能動態刷新配置 使 Bean 能夠在運行時動態刷新配置屬性當配置中心的配置發生變化時&#xff0c;無需重啟應用即可生效作用域管理 為 Bean 創建一個特殊的作用域 refresh標記的 Bean …

Flutter SDK 安裝與國內鏡像配置全流程(Windows / macOS / Linux)

這是一份面向國內網絡環境的 Flutter 從零到可運行指引&#xff1a;覆蓋 SDK 安裝、平臺依賴準備、國內鏡像配置&#xff08;PUB_HOSTED_URL、FLUTTER_STORAGE_BASE_URL&#xff09;、Android 側 Gradle 倉庫加速&#xff0c;以及 Java/Gradle 版本兼容的關鍵坑位與排查思路。文…

【Java】NIO 簡單介紹

簡介 從 Java 1.4 版本開始引入的一個新的 I/O API&#xff0c;可以替代標準的 Java I/O。提供了與標準 I/O 不同的工作方式&#xff0c;核心是 通道&#xff08;Channel&#xff09;、緩沖區&#xff08;Buffer&#xff09; 和 選擇器&#xff08;Selector&#xff09;。支持非…

Java爬蟲獲取京東item_get_app數據的實戰指南

一、引言京東開放平臺提供了豐富的API接口&#xff0c;其中item_get_app接口可用于獲取商品的詳細信息。這些數據對于市場分析、價格監控、商品推薦等場景具有重要價值。本文將詳細介紹如何使用Java編寫爬蟲&#xff0c;通過調用京東開放平臺的item_get_app接口獲取商品詳情數據…

Vue3源碼reactivity響應式篇之批量更新

概述 在vue3響應式系統設計中&#xff0c;批量更新是優化性能的核心機制之一。當短時間內頻繁多次修改響應式數據時&#xff0c;批量更新可以避免頻繁觸發訂閱者的更新操作&#xff0c;將這些更新操作合并為一次&#xff0c;從而減少不必要的計算和DOM操作。 批量更新也是利用鏈…

AI 模型訓練過程中參數用BF16轉向FP16的原因

大模型訓練從 FP16 轉向 BF16 是一個關鍵的技術演進&#xff0c;其核心原因在于 BF16 在動態范圍和精度之間取得了更優的平衡&#xff0c;從而極大地提升了訓練&#xff08;尤其是大模型訓練&#xff09;的穩定性和有效性。 1. 背景 為什么需要半精度浮點數 (FP16)&#xff1f;…

python網絡爬取個人學習指南-(五)

**************************************************************************************************************author&#xff1a;keyinfodate&#xff1a;2025-09-09 23:50title&#xff1a;網絡信息爬取之多聯級標題內容點擊****************************************…

RAG - 檢索增強生成

第一部分&#xff1a;RAG 詳解一、RAG 是什么&#xff1f;RAG&#xff08;Retrieval-Augmented Generation&#xff0c;檢索增強生成&#xff09;是一種將信息檢索&#xff08;或知識檢索&#xff09;與大語言模型&#xff08;LLM&#xff09;的生成能力相結合的技術框架。它的…

大數據畢業設計選題推薦-基于大數據的分化型甲狀腺癌復發數據可視化分析系統-Spark-Hadoop-Bigdata

?作者主頁&#xff1a;IT研究室? 個人簡介&#xff1a;曾從事計算機專業培訓教學&#xff0c;擅長Java、Python、微信小程序、Golang、安卓Android等項目實戰。接項目定制開發、代碼講解、答辯教學、文檔編寫、降重等。 ?文末獲取源碼? 精彩專欄推薦??? Java項目 Python…

Spring Bean掃描

好的&#xff0c;沒有問題。基于我們之前討論的內容&#xff0c;這是一篇關于 Spring Bean 掃描問題的深度解析博客。Spring Bean掃描作者&#xff1a;Gz | 發布時間&#xff1a;2025年9月9日&#x1f3af; Spring如何找到你的Bean&#xff1f; 首先要理解原理。Spring的組件掃…

【 運維相關】-- HTTP 壓測/負載發生器之新秀 oha

目錄 oha 項目分析&#xff08;hatoo/oha&#xff09; 一、概述 二、安裝 三、快速上手 三、常用參數&#xff08;摘選&#xff09; 四、輸出解讀&#xff08;終端 TUI&#xff09; 五、與其它工具對比 六、最佳實踐 七、注意事項 八、參考 oha 項目分析&#xff08;h…

淘寶閃購基于FlinkPaimon的Lakehouse生產實踐:從實時數倉到湖倉一體化的演進之路

摘要&#xff1a;本文整理自淘寶閃購(餓了么)大數據架構師王沛斌老師在 Flink Forward Asia 2025 城市巡回上海站的分享。引言在數字化轉型的浪潮中&#xff0c;企業對實時數據處理的需求日益增長。傳統的實時數倉架構在面對業務快速變化和數據規模爆炸性增長時&#xff0c;逐漸…

Android應用添加日歷提醒功能

功能 在安卓應用里調用系統日歷&#xff0c;直接創建一個帶提醒的日歷事件&#xff0c;甚至不需要跳轉到日歷界面&#xff0c;只需要獲取系統日歷的讀取權限即可。 需要的權限 在AndroidManifest.xml里添加 <uses-permission android:name"android.permission.READ_CAL…

?Git Bisect 二分查找定位錯誤總結

# Git Bisect 二分查找指南## 1. 基本原理&#xff08;ASCII示意圖&#xff09; 假設提交歷史是一條時間線&#xff0c;Ggood&#xff08;正常&#xff09;&#xff0c;Bbad&#xff08;異常&#xff09;&#xff1a;提交順序: G --- G --- G --- B --- B --- B | | | 初始正常…

ThingsKit物聯網平臺 v2.0.0 發布|前端UI重構、底層架構升級

v2.0.0 Release發布日期&#xff1a;2025/08/25 代碼標簽&#xff1a;v2.0.0_Release&#x1f947; 新增功能國標級聯&#xff08;支持上級、下級國標級聯&#xff09;視頻回放、錄像計劃&#xff08;用戶可以通過錄像計劃生成對應的視頻回放并查看&#xff09;Modbus_TCP協…

Lua > Mac Mini M4安裝openresty

Mac Mini M4安裝openresty 主要參考 https://www.cnblogs.com/helios-fz/p/15703260.html brew uninstall nginxbrew update brew install pcre openssl #brew install geoip# brew tap openresty/brew # brew install openresty # brew install openresty/brew/openresty# VER…