Linux之線程

Linux之線程

  • 線程之形
  • 線程接口
  • 線程安全
    • 互斥鎖
    • 條件變量&信號量
    • 生產者與消費者模型
    • 線程池

線程之形

進程是資源分配的基本單位,而線程是進程內部的一個執行單元,也是 CPU 調度的基本單位。
線程之間共享進程地址空間、文件描述符與信號處理,但也有獨立資源:寄存器、棧、線程ID和調度優先級等。
線程切換由于地址空間相同,上下文切換時寄存器切換和內存地址緩存諸如頁表緩存TLB(快表)及硬件緩存切換成本比進程切換低得多。
Linux下的線程并非標準的、獨立于進程實現的線程(參見windows實現線程),而是通過pthread庫封裝了輕量級進程LWP(light weight process)來模擬線程。具體的說法,詳見下文。

說Linux的線程是用LWP模擬的意思是,Linux利用了進程的概念和機制來實現線程的功能,通過讓不同的線程共享某些資源來達到所謂的“輕量級”效果。這種方式使得線程既能夠享受到與進程相似的隔離性和保護性,又能夠在同一程序內部高效地進行數據交換和通信。另,ps -aL查看LWP即線程信息。之前的ps -axj只能查看進程級別信息。

線程接口

  • 線程創建:int pthread_create(pthread_t *restrict thread,const pthread_attr_t *restrict attr,void *(*start_routine)(void *),void *restrict arg);,thread輸出型參數,存儲用戶層線程ID;attr線程屬性,給NULL即可;start_routine線程執行函數;arg傳給前者的參數。

pthread_create是glibc庫提供的接口,它實際上,調用mmap()在堆區分配struct pthread(線程控制塊 TCB,庫描述與管理線程的結構體,存儲內核級tid,線程棧指針與大小,TLS指針和線程狀態、返回值等)和固定大小的線程棧以及線程局部存儲(TLS,存儲私有變量如errno),再調用int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ... /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );fn即線程執行函數,arg其參數,child_stack傳mmap出來的線程棧棧底地址,flags選項較多自行了解。然后,內核再創建一個task_struct描述新線程,其mm_struct指向同一個地址空間,pid實為內核級tid(t即thread),tgid線程組id為進程id(主線程tid和pid和進程pid是同一個)。而mmap區的struct pthread的起始虛擬地址即為用戶層線程ID,作為上面函數第一個參數帶出。

線程局部存儲,在全局內置類型變量前加__thread修飾,使之成為各個線程局部存儲區變量而非全局區變量。另外,pthread_setname_np(pthread_t,const char*)可將變量放至局部存儲,實現取名字;pthread_getname_np(pthread_t,char*,size_t)得之。

  • 線程終止:void pthread_exit(void *retval);終止當前線程,retval即線程返回值。注意,exit()終止進程。
  • 等待線程結束:int pthread_join(pthread_t thread, void **retval);阻塞等待指定ID線程,retval帶出上面的返回值。而線程返回值在終止后會被存放在struct pthread里,等join時拿出來。
  • 線程分離:int pthread_detach(pthread_t thread);將指定線程置于分離狀態,系統會在該線程結束后自動回收其資源而無需等待。可搭配pthread_t pthread_self(void);分離自己。

線程終止還包括在執行函數return和線程取消int pthread_cancel(pthread_t thread);,后者給join的retval為-1。如果調用join則會釋放其struct pthread和線程棧以及task_struct,如果detach則結束自動銷毀它們。注意,動態開辟的堆區內存需要手動釋放,否則內存泄漏。

線程安全

線程安全指多個線程并發訪問共享資源時不出因為線程切換等引發的問題。通常需要互斥鎖、條件變量等方案來保證。

互斥鎖

臨界資源是一次僅允許一個執行流使用的共享資源,臨界區是訪問臨界資源的那段代碼,互斥是多線程并發競爭式訪問臨界資源時、同一時間只有一個線程能進入臨界區的情況。
互斥鎖實際上就是同一時刻只讓拿到鎖的線程進入臨界區,讓并行變成串行訪問。
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);初始化鎖,后參為屬性通常NULL,全局鎖也可用PTHREAD_MUTEX_INITIALIZER初始化;pthread_mutex_lock(pthread_mutex_t *mutex);阻塞式獲取鎖,非阻塞與定時自行了解;pthread_mutex_unlock(pthread_mutex_t *mutex);釋放鎖;pthread_mutex_destroy(pthread_mutex_t *mutex);銷毀鎖。
鎖本身作為臨界資源被訪問,多線程并發去lock時是怎么保證互斥的?
偽代碼如下:

lock:movb $0, %al//原子性將al寫入0xchgb %al, mutex//原子性交換鎖和al的內容,鎖初始為1if(al寄存器的內容 > 0)return 0;//搶到鎖了else掛起等待;goto lock;
unlock:movb $1, mutex//原子喚醒等待Mutex的線程;return 0;

原子性指一個操作只有01兩態,即有無兩態,無中間態。原子操作就是遵守原子性的操作。上面鎖的代碼中寫入movb和交換xchgb為原子操作,如果一個線程搶到了鎖,則mutex里為0,al里為1,其他線程永遠拿不到這個1,因為mutex里為0,除非該線程unlock,再把1放回mutex。
關于RAII風格的lockguard,即構造lock mutex,析構unlock之。

條件變量&信號量

同步值在互斥前提下,多線程按序訪問臨界資源。
條件變量Condition即允許多線程排隊等待某個條件變量就緒,等候通知從而按序訪問臨界資源。
pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);初始化條件變量,也可PTHREAD_COND_INITIALIZER;pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);等待條件,后參為互斥鎖,該函數會1先解鎖,既防止死鎖(因為其他線程無法拿到鎖并修改條件、發出通知)也提高性能,允許其他線程訪問臨界資源,2阻塞等待,進入條件變量的等待隊列中,3一旦被喚醒成功,重新獲取并上原來的鎖。該函數應在while(檢測條件)內部使用,因為存在偽喚醒(比如因為系統中斷或異常處理、內核優化等導致調度變化)或等待失敗、函數返回的情況;pthread_cond_signal(pthread_cond_t *cond);喚醒一個等待該條件的線程;pthread_cond_broadcast(pthread_cond_t *cond);喚醒所有;pthread_cond_destroy(pthread_cond_t *cond);銷毀之。
信號量Semaphore(此處是POSIX標準下的)是一種預定機制,想象去電影院前先買票再排隊入場,信號量就是票,所有人互斥(通過原子操作保證)搶票來預定座位,然后排隊進場看電影。
int sem_init(sem_t *sem, int pshared, unsigned int value);初始化信號量,二參0為線程間共享、非0進程間共享,三參為初始值;sem_wait(sem_t *sem); // 如果信號量值大于0,則減1;否則阻塞P操作,申請信號量即信號量減1,類比買票;sem_post(sem_t *sem); V操作,釋放信號量即信號量加1,類比退票或放票。

生產者與消費者模型

多個生產者并行生產商品,串行投入商品至超市,多個消費者串行拿取商品出超市,并行消費商品。
3種關系,生產者之間互斥,消費者之間互斥,生消之間互斥且同步;2種角色,生消;1個交易場所,以特定結構構成的內存空間。
可以通過阻塞隊列存放任務+鎖+條件變量同步等待(生產者生產任務了通知等待的消費者、滿了等待消費者通知,消費者消費任務了通知等待的生產者、完了等待生產者通知)實現,也可以通過環形隊列存放任務+鎖+信號量(生產者對空位量P操作、任務量V操作,消費者對空位量V操作、任務量P操作)實現。

線程池

提前創造一批線程,等待任務到來,來一個召喚一個線程去處理一個。可采用鎖+條件變量的方式實現。


最后兩個模塊的代碼具體實現,還沒考慮好是否要呈現以及如果要呈現的話要怎么呈現,所以只提供了思路。
線程over,終于進入網絡部分了,理論系統學習生涯結束指日可待啊!

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

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

相關文章

snail-job的oracle sql(oracle 11g)

官網版本的oracle sql中有自增主鍵,oracle 11g并不支持,所以改成新建索引和觸發器的方式自增主鍵。(tip:snail-job的最新版本1.0.0必須使用JDK17, jdk8會報錯,所以最后沒用起來) /*SnailJob Dat…

Windows VMWare Centos Docker部署Nginx并配置對Springboot應用的訪問代理

前置博文 Windows VMWare Centos環境下安裝Docker并配置MySqlhttps://blog.csdn.net/u013224722/article/details/148928081 Windows VMWare Centos Docker部署Springboot應用https://blog.csdn.net/u013224722/article/details/148958480 # 將已存在的容器設置為宿主機重啟后…

暑期數據結構第一天

暑期數據結構第一天 數據元素與數據對象 數據元素--組成數據的基本單位 與數據的關系:是集合的個體 數據對象--性質相同的數據元素的集合 與數據的關系:集合的子集 邏輯結構 (1)線性結構,所有結點都最多有一個直…

vsCode 擴展中 package.nls.json 文件的作用國際化支持

package.nls.json 代表英文語言文件 {"command.favourite.addtofavourite": "Add to Favourite","command.favourite.deletefavourite": "Remove from Favourite","command.favourite.moveup": "Move Up" } 在 …

結構型智能科技的關鍵可行性——信息型智能向結構型智能的轉換(提綱)

結構型智能科技的關鍵可行性 ——信息型智能向結構型智能的轉換 1.信息型智能科技概述 1.1傳統計算機科技的信息型繼承者 1.2 信息型智能環境 1.3信息型智能主體 1.4機器學習創造的智能 1.5信息型智能科技的問題 2.結構型智能科技概述 2.1傳統計算機科技向真實生命結構…

Excel 數據合并助手SheetDataMerge智能識別同類數據,銷售報表處理提升效率

各位Excel小能手們!今天給大家介紹個超厲害的玩意兒——SheetDataMerge,這可是專注Excel數據處理的實用工具!它就像個數據小管家,核心功能就是智能合并工作表里的同類數據。 軟件下載地址安裝包 它有多牛呢?能自動識別…

AIStarter平臺使用指南:如何一鍵卸載已下載的AI項目(最新版操作教程)

如果你正在使用 AIStarter 平臺,但不知道如何卸載不再需要的 AI 項目,那么這篇簡明教程將為你提供清晰的操作指引。 AIStarter 是由知名創作者“熊哥”打造的一款 AI 工具啟動器平臺,旨在幫助用戶快速部署和運行各類 AI 項目。隨著平臺不斷更…

項目中大表治理方案實踐

一、業務背景 目前生產庫數據庫服務器數據存儲達到了13T,其中license_spart表數據量達到了200億,占用7.5T,空間占用率達到54%。而且這張表每年數據增長量達到30億。其中有效VALID數據占20億,無效數據INVALID占180億。由于業務上有…

快應用(QuickApp)技術解析與UniApp跨端開發生態探秘優雅草卓伊凡

快應用(QuickApp)技術解析與UniApp跨端開發生態探秘優雅草卓伊凡引言:一場由快應用引發的技術辯論近日,優雅草科技的資深開發者卓伊凡在與甲方的一次項目溝通中,因技術選型問題展開了激烈討論。甲方對快應用&#xff0…

《Font Awesome 參考手冊》

《Font Awesome 參考手冊》 引言 Font Awesome 是一個功能豐富的圖標庫,旨在幫助設計師和開發者快速地在網頁上添加圖標。它提供了超過700個矢量圖標,并且支持響應式設計。本文將為您詳細介紹 Font Awesome 的使用方法、圖標分類、圖標定制以及與 CSS 的結合。 一、Font A…

Linux基本命令篇 —— uname命令

uname命令是Linux系統中用于顯示系統信息的實用工具,它可以提供關于操作系統、內核版本、硬件架構等重要信息。下面我將詳細介紹這個命令的用法和常見應用場景。 目錄 一、基本語法 二、常用選項 三、使用示例 顯示所有系統信息(最常用) …

React Native 開發環境搭建--window--android

官網: https://reactnative.cn/docs/environment-setup 必須安裝的 node, JDK ,android Studio 安裝node 以前裝了nvm, 用nvm install 18.0.0 就可以了 安裝JDK 1、下載 ---- 我安裝的是11 【JAVA17下載傳送門】 注意!!!1 …

ODS 系統是什么?企業為什么需要搭建 ODS?

目錄 一、ODS 系統基礎認知:先弄明白它是啥 1. 什么是 ODS 系統? 2. ODS 系統的起源 3. ODS 系統的特點 二、ODS 系統能干啥?核心功能解析 1. 數據集成 2. 數據清洗和轉換 3. 實時數據更新 4. 數據查詢和分析 三、企業為什么非得搭…

通過網頁調用身份證閱讀器http websocket方法-華視電子————仙盟創夢IDE

1.安裝全瀏覽器網頁專用監控軟件 2.安裝后 3.配置web接口 4.測試讀取 5.驅動監控地址 時間段內讀取身份證:如超時時間10000ms,則在點擊按鈕10秒內,放上身份證就可以讀成功,超時返回失敗; 讀身份證:把身份證放上去后點擊讀卡,讀成功,再次讀卡需要將身份證拿起來再放回去; 不拿…

Spring Cloud 前端調用后端接口方式

在 Spring Cloud 微服務架構中,前端調用后端接口通常不直接通過 Eureka,而是通過以下兩種核心方式實現: 一、前端直接調用后端服務(需解決跨域和地址管理問題) 1. AJAX 直接調用 前端通過 HTTP 請求(如 …

【stm32】HAL庫開發——CubeMX配置RTC,單片機工作模式和看門狗

目錄 一、CubeMX配置RTC 1.RTC實時重要一環——BKP 寄存器 2.RTC實時時鐘 2.1打開RTC并設置時間 2.2打開外部低速時鐘 2.3代碼實現: 二、單片機工作模式 1.低功耗睡眠模式(Sleep) 2.低功耗停止模式(Stop) 3.低功耗待機模式(StandBy) 三、看門狗 1.獨立看…

9.Docker的容器數據卷使用(掛載)

什么是容器數據卷技術? 到這里,我算是入門docker了! docker的理念:將環境和應用打包成一個鏡像!直接安裝就能使用 如果數據都在容器中,那么我們一旦將容器刪除,數據就會丟失!因為…

使用 TCollector 寫入 TDengine

TCollector 是 openTSDB 的一部分,它用來采集客戶端日志發送給數據庫。 只需要將 TCollector 的配置修改指向運行 taosAdapter 的服務器域名(或 IP 地址)和相應端口即可將 TCollector 采集的數據存在到 TDengine 中,可以充分利用…

高斯消元法詳解

文章目錄 概念用法特殊情況 我的奇怪方法 概念 什么是高斯消元?讓我們看一看 OI-Wiki 的解釋: 高斯消元法(Gauss–Jordan elimination)是求解線性方程組的經典算法,它在當代數學中有著重要的地位和價值,是線性代數課…

暴雨服務器成功中標華中科技大學集成電路學院服務器采購項目

近日,武漢暴雨信息發展有限公司在激烈的競爭中脫穎而出,成功中標華中科技大學集成電路學院的服務器采購項目。此次中標產品為暴雨旗下的塔式重裝AM400服務器,這一成果標志著暴雨信息在高性能計算領域的卓越實力得到了高校科研機構的高度認可。…