Linux 線程:從零構建多線程應用:系統化解析線程API與底層設計邏輯

線程

線程的概述

在之前,我們常把進程定義為 程序執行的實例,實際不然,進程實際上只是維護應用程序的各種資源,并不執行什么。真正執行具體任務的是線程。

那為什么之前直接執行a.out的時候,沒有這種感受呢?

那是因為每一個進程中都會有一個主線程,我們默認執行的就是這個主線程。

線程創建比進程簡單

進程通過返回值確定 是哪塊進程的代碼。

線程不需要,創建一個線程,比較簡單,像回調函數一樣,調用線程創建函數,在對應函數體中 操作這一線程即可。

從這往下的概述部分 重點(理解背誦)

進程是系統分配資源的基本單位,線程是CPU執行基本調度的基本單位

比如 如果線程是具體某個人,那么進程就是指部門

線程可以看作一個輕量級的進程(LWP:light weight process),在Linux環境下線程的本質仍是進程

進程 必須至少包含一個線程

線程依賴于進程,線程共享進程的資源,線程的系統資源有(計數器,一組寄存器和棧)

進程結束?當前進程的所有線程 都將立即結束

Linux內核是不區分進程和線程的,只有在用戶層面上進行區分。所以,進程所有操作函數pthread*是庫函數,而并非系統調用

線程共享資源

  1. 文件描述符
  2. 每種信號的處理方式
  3. 當前工作目錄
  4. 用戶ID和組ID 內存地址空間

線程非共享資源

  1. 線程id
  2. 處理器現場和棧指針
  3. 獨立的棧空間
  4. errno變量
  5. 信號屏蔽字
  6. 調度優先級

線程被CPU調度,因此線程中有調度優先級,且線程間不共享

查看指定進程的線程號的命令:ps -Lf pid(進程號)

線程的API

API介紹用的代碼 較簡短的代碼我用圖片展示。

只要看到了pthread.h 頭文件,我們在編譯的時候就需要加上 -lpthread

pthread_t 是無符號長整型

1、查看線程號

#include <pthread.h>

pthread_t pthread_self(void);

功能:

????????查看線程號

參數:

????????無參

返回值:

????????調用該函數的線程 的 線程ID

代碼演示

代碼運行結果

線程ID(通過pthread_self得到) 和 IPW(輕量級進程)的區別

大家看這張圖,可以看到這兩個值有明顯的區別

在Linux中,線程就是LWP(輕量級進程),全局唯一,由操作系統內核分配,用于系統調度和資源管理。

線程ID呢僅在同一進程內有效,是抽象標識符。由?pthread 庫在進程內維護。

2、創建線程

#include <pthread.h>

int pthread_create(pthread_t *thread,

????????????????????????????????const pthread_attr_t *attr,

????????????????????????????????void *(*start_routine) (void *),

????????????????????????????????void *arg);

功能:

????????創建一個線程

參數:

????????thread:線程標識符地址

????????attr:線程屬性結構體地址,通常設置為NULL

????????????????屬性這個參數,我們現在填寫NULL,下面我會詳細說一下這個參數。

????????start_routine:線程函數的入口地址

????????arg:傳遞給線程函數的參數

返回值:

????????成功:0

????????失敗:非0

代碼演示 案例1

注意這里主進程一定要阻塞,因為進程結束,線程也會關閉

代碼運行結果

案例二 創建進程,每個線程有自己的線程函數

代碼運行結果是一樣的,大家只要知道能夠這樣用就可以了。

3、回收線程函數

函數介紹

功能:

????????等待線程結束(此函數會阻塞),并回收線程資源。如果線程已結束,那么該函數會立即返回。

參數:

????????thread:被等待的進程的進程ID

????????retval:用來存儲線程退出狀態的指針的地址

????????這里細說一下:retval的返回值類型我們可以看到是void **,這個變量需要用戶創建,用來存儲創建函數 線程執行函數的 返回值,返回值時void*類型。由于我們要得到它,就要提前創建一個void *的變量,再通過函數修改我們創建的變量為返回值的內容,由于是函數內部要函數外部的變量的值,因此需要傳遞所創建void *的變量的地址,因此時void **類型。

返回值:

????????成功:0

????????失敗:非0

代碼演示

代碼運行結果

注意

由于帶阻塞,因此有順序,如下面這種情況

先等待tid1結束,回收tid1后,才會回收tid2

不管誰先結束,都是先1 后2

進程分離

創建好線程后,當多個任務同時進行,用上面的方法,會阻塞線程的釋放,導致資源浪費(長時間不適用卻霸占內存),因此這里 我們就將其分離出去,把釋放工作交給系統,系統發現它結束,就會釋放

由于它的歸屬權已經歸于系統,此時我們就不可以再對它使用join

注意這里的分離,并不是該線程不依賴于進程,而是將 釋放線程獨立資源 的權限交給了系統,進程還是依賴與進程的,依舊共享進程的空間

函數介紹

#include <pthread.h>

int pthread_detach(pthread_t thread);

功能:

????????使調用線程的獨立資源回收工作與當前進程分離

參數:

????????thread:線程ID

返回值:

????????成功:0

????????失敗:非零

代碼演示 主線程和子線程

本代碼將實現 主線程和子線程 一起運行,并且利用主線程的正常工作,來驗證pthread_detach的不阻塞的特性

代碼運行結果

4、線程的取消和退出

????????注意要退出線程 一定不要調用exit或者_exit 這兩個是退出進程的函數,如果調用這個在線程中知道你的進程是什么,它會將進程退出,進程退出會導致所有的線程退出,那么我們該怎么讓單個線程退出呢?

1、線程的退出(自殺)

#include <pthread.h>

void pthread_exit(void *retval);

函數功能:

????????退出調用線程。一個進程中的多個線程是共享該進程的數據段的,因此通常線程退出后,所占用的資源并不會釋放。

參數:

????????retval:存儲線程退出狀態的指針(return后的數據)

返回值:

????????無

2、線程的取消(他殺)

取消本線程,也可以取消當前進程的其他線程

#include <pthread.h>

int pthread_cancel(pthread_t thread);

功能:

????????退出調用線程。一個進程中的多個線程是共享該進程的數據段的,因此通常線程退出后,所占用的資源并不會釋放。

參數:

????????thread:目標線程ID

返回值:

????????成功:0

????????失敗:出錯編號

注意

????????殺死線程也不是立刻就能完成,必須要到達取消點

????????取消點:是線程檢查是否被取消,并按請求進行動作的一個位置。通常是一些系統調用

代碼演示:

代碼功能:子線程1實現5s后自殺,子線程2在7s時殺死子線程3,子線程2在10s時殺死自己。

這里我們會與遇到一個問題:當我們在線程2 中,我們首先需要傳入本線程的名字(線程2),還需要傳入子線程3的線程ID,我們該如何實現傳兩個參數呢?

答案在代碼中,大家自己查看。

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>//傳遞兩個參數的辦法就是借助結構體,將線程名和ID作為結構體成員后,將結構體傳入 線程調用函數 中即可
//并且如果要實現tid3的修改同步到結構體內,需要傳遞tid3的指針類型
typedef struct dataDouble
{char name[32];pthread_t *id;
}DATA;//線程調用函數聲明
void *my_fun1(void *arg);
void *my_fun2(void *arg);
void *my_fun3(void *arg);
int main(int argc, char const *argv[])
{//創建線程ID遍歷(存放線程ID)pthread_t tid1,tid2,tid3;DATA *tid2_data = (DATA *)calloc(1,sizeof(DATA));tid2_data->id = &tid3;strcpy(tid2_data->name,"子進程2");//創建線程pthread_create(&tid1,NULL,my_fun1,(void *)"子線程1");pthread_create(&tid2,NULL,my_fun2,(void *)tid2_data);pthread_create(&tid3,NULL,my_fun3,(void *)"子線程3");//釋放線程pthread_detach(tid1);pthread_detach(tid2);pthread_detach(tid3);//阻塞進程while(1);//釋放結構體申請空間,一定要在全部線程結束之后free(tid2_data);return 0;
}
//線程調用函數體實現
void *my_fun1(void *arg)//線程1 在5s的時候自殺
{int i = 0;while(1){sleep(1);printf("----%s的運行時間為:%d\n",(char *)arg,++i);if(i == 5){pthread_exit(NULL);}}
}
void *my_fun2(void *arg)//線程2 在7s的時候殺死線程3,在10s的時候自殺(使用cancel)
{DATA data = *(DATA *)arg;int i = 0;while(1){sleep(1);printf("--------%s的運行時間為:%d\n",data.name,++i);if(i == 7){pthread_cancel(*data.id);}if(i == 10){pthread_cancel(pthread_self());}}
}
void *my_fun3(void *arg)
{int i = 0;while(1){sleep(1);printf("------------%s的運行時間為:%d\n",(char *)arg,++i);}
}

代碼運行結果

結束

代碼重在練習!

代碼重在練習!

代碼重在練習!

今天的分享就到此結束了,希望對你有所幫助,如果你喜歡我的分享,請點贊收藏夾關注,謝謝大家!!!

下篇介紹:線程的屬性介紹,線程池的簡述,多線程的建立

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

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

相關文章

014_多線程

多線程 多線程創建線程方式一&#xff1a;繼承Thread類方式二&#xff1a;實現Runable接口方式三&#xff1a;實現Callbale接口 Thread的常用方法線程安全線程同步方式一&#xff1a;同步代碼塊同步方法方式三&#xff1a;Lock鎖 線性池創建線程池處理Runnable任務處理Callable…

機場跑道異物檢測數據集VOC+YOLO格式33793張31類別

數據集分辨率都是300x300,都是貼近地面拍攝&#xff0c;具體看圖片 據集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路徑的txt文件&#xff0c;僅僅包含jpg圖片以及對應的VOC格式xml文件和yolo格式txt文件) 圖片數量(jpg文件個數)&#xff1a;33793 標注數量(xml文件…

Spring Cloud 遠程調用

4.OpenFeign的實現原理是什么&#xff1f; 在使用OpenFeign的時候&#xff0c;主要關心兩個注解&#xff0c;EnableFeignClients和FeignClient。整體的流程分為以下幾個部分&#xff1a; 啟用Feign代理&#xff0c;通過在啟動類上添加EnableFeignClients注解&#xff0c;開啟F…

Unity中使用FMETP STREAM傳輸實時畫面

一、客戶端&#xff08;發送端&#xff09; 總體思路&#xff1a;先把畫面編碼Encoder&#xff0c;再發送給服務端 新建場景&#xff0c;創建一個實體&#xff0c;名為FMnet&#xff0c;添加組件FMNetworkManager&#xff0c;將NetworkType設置為客戶端Client&#xff0c;設置…

Baklib三步構建企業內容中臺

需求調研構建內容中臺 企業內容中臺建設的首要環節在于精準識別業務需求與知識管理痛點。通過Baklib 是什么類型的工具的定位分析可知&#xff0c;其作為知識管理中樞&#xff0c;能夠系統梳理客戶服務場景中的高頻咨詢、產品文檔更新需求及跨部門協作流程。在需求調研階段&am…

實現抗隱私泄漏的AI人工智能推理

目錄 什么是私人AI? 什么是可信執行環境? TEE 如何在 AI 推理期間保護數據? 使用 TEE 是否存在風險? 有哪些風險? Atoma 如何應對這些風險 為什么去中心化網絡是解決方案 人工智能推理過程中還有其他保護隱私的方法嗎? 私人人工智能可以實現什么? 隱私驅動的應…

一、TorchRec里邊的輸入輸出類型

TorchRec中的輸入和輸出格式 文章目錄 TorchRec中的輸入和輸出格式前言一、JaggedTensor1.1 核心概念1.2 核心屬性&#xff0c;也就是參數1.3 關鍵操作與方法 二、KeyedJaggedTensor2.1 核心概念2.2 核心屬性&#xff0c;也就是參數 3、KeyedTensor總結 前言 TorchRec具有其特…

JAVA實現在H5頁面中點擊鏈接直接進入微信小程序

在普通的Html5頁面中如何實現點擊URL鏈接直接進入微信小程序&#xff0c;不需要掃描小程序二維碼&#xff1f; 網上介紹的很多方法是在小程序后臺設置Schema&#xff0c;不過我進入我的小程序后臺在開發設置里面 沒有找到設置小程序Schema的地方&#xff0c;我是通過調用API接口…

uniapp解決上架華為應用市場審核要求-監聽權限的申請

支持android平臺全局監聽權限的申請。當申請權限時&#xff0c;會在頁面頂部顯示申請權限的目的。主要解決上架華為應用市場審核要求&#xff1a;APP在調用終端權限時&#xff0c;應同步告知用戶申請該權限的目的。 因為如果不提示&#xff0c;你上架應用市場會被打打回來 Tip…

文件IO5(JPEG圖像原理與應用)

JPEG圖像原理與應用 ? 基本概念 JPEG&#xff08;Joint Photographic Experts Group&#xff09;指的是聯合圖像專家組&#xff0c;是國際標準化組織ISO制訂并于1992年發布的一種面向連續色調靜止圖像的壓縮編碼標準&#xff0c;所以也被稱為JPEG標準。 同樣&#xff0c;JP…

vue3 history路由模式刷新頁面報錯問題解決

在使用history路由模式時刷新網頁提示404錯誤&#xff0c;這是改怎么辦呢。 官方解決辦法 https://router.vuejs.org/zh/guide/essentials/history-mode.html

3D激光輪廓儀知識整理(待完善)

文章目錄 1.原理和應用場景1.1 相機原理1.1.1 測量原理1.1.2 相機激光器1.1.3 沙姆鏡頭1.1.4 相機標定1.1.5 中心線提取 1.2 應用場景1.2.1 測量相關應用1.2.2 缺陷檢測相關應用 2.相機參數介紹及選型介紹2.1 成像原理2.2 原始圖成像2.3 生成輪廓圖2.4 相機規格參數2.4.1 單輪廓…

w285藥店管理系統的設計與實現

&#x1f64a;作者簡介&#xff1a;多年一線開發工作經驗&#xff0c;原創團隊&#xff0c;分享技術代碼幫助學生學習&#xff0c;獨立完成自己的網站項目。 代碼可以查看文章末尾??聯系方式獲取&#xff0c;記得注明來意哦~&#x1f339;贈送計算機畢業設計600個選題excel文…

Google Chrome Canary版官方下載及安裝教程【適用于開發者與進階用戶】

谷歌瀏覽器&#xff08;Google Chrome&#xff09;以其高性能、強擴展性和良好的用戶體驗深受全球用戶喜愛。在其多個版本中&#xff0c;Chrome Canary因具備最前沿的功能測試環境&#xff0c;成為開發者和技術探索者的首選。如果你希望第一時間體驗Google Chrome最新功能&…

RocketMQ深度百科全書式解析

?一、核心架構與設計哲學? ?1. 設計目標? ?海量消息堆積?&#xff1a;單機支持百萬級消息堆積&#xff0c;適合大數據場景&#xff08;如日志采集&#xff09;。?嚴格順序性?&#xff1a;通過隊列分區&#xff08;Queue&#xff09;和消費鎖機制保證局部順序。?事務…

每日一題(小白)暴力娛樂篇19

樣例&#xff1a; 6 1 1 4 5 1 4 輸出&#xff1a; 56 66 52 44 54 64 分析題意可以得知&#xff0c;就是接收一串數字&#xff0c;將數字按照下標每次向右移動一位&#xff08;末尾循環到第一位&#xff09;&#xff0c;每次移動玩計算一下下標和數字的乘積且累加。 ①接收…

如何應對“最后時刻任務堆積”(鼓包現象)

應對“最后時刻任務堆積”&#xff08;鼓包現象&#xff09;的方法包括&#xff1a;合理規劃項目時間表、強化進度跟蹤管理、明確任務優先級、有效的資源配置、提升團隊溝通效率。其中&#xff0c;強化進度跟蹤管理尤為關鍵。根據項目管理協會&#xff08;PMI&#xff09;的調查…

19C-19.3環境-impdp導入到view時卡死

幫客戶導入一個用戶時&#xff0c;發現VIEW部分無法進行下去 Processing object type SCHEMA_EXPORT/TABLE/IDENTITY_COLUMN Processing object type SCHEMA_EXPORT/PACKAGE/PACKAGE_SPEC Processing object type SCHEMA_EXPORT/FUNCTION/FUNCTION Processing object type SCH…

一、簡單的 Django 服務

一、配置虛擬環境 1.1 創建一個文件夾在導航欄輸入cmd打開 1.2 安裝依賴兩個庫 pip install virtualenv virtualenvwrapper-win -i https://pypi.tuna.tsinghua.edu.cn/simple驗證是否安裝成功 virtualenv --version pip show virtualenvwrapper-win 1.3 創建虛擬環境 mkvi…

道路運輸安全員崗位事項有哪些?

道路運輸安全員的崗位事項主要包括以下幾個方面&#xff1a; 安全制度與計劃 參與制定和完善道路運輸企業的安全管理制度、安全操作規程等&#xff0c;確保各項安全工作有章可循。協助制定年度安全工作計劃和目標&#xff0c;并負責組織實施和監督執行情況&#xff0c;定期對…