Linux: 線程控制

目錄

一 前言

二 線程控制

1. POSIX線程庫(原生線程庫)

2. 創建線程

2.1 pthread_create

?2.2pthread_self()獲取線程id

?3.線程終止

3.1.return 方式

3.2 pthread_exit?

?4 線程等待

三 理解線程tid?


一 前言

? ?在上一篇文章中我們已經學習了線程的概念,線程的創建,并且已經從根本上了解了線程和進程的相同點及不同點。在學習進程時,我們學習了進程的相關概念,進程控制接口,而線程作為更輕量級的進程,其自然也有著控制接口。?


二 線程控制

1. POSIX線程庫(原生線程庫)

  • 與線程有關的函數構成了一個完整的系列,絕大多數函數的名字都是以“pthread_”打頭的
  • 要使用這些函數庫,要通過引入頭文 件 <pthread.h>
  • 鏈接這些線程函數庫時要使用編譯器命令的“-lpthread”選項

2. 創建線程

2.1 pthread_create

功能:創建一個新的線程

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void * (*start_routine)(void*), void *arg);

  1. 參數 thread:返回線程ID
  2. attr:設置線程的屬性,attr為NULL表示使用默認屬性
  3. start_routine:是個函數地址,線程啟動后要執行的函數
  4. arg:傳給線程啟動函數的參數
  5. 返回值:成功返回0;失敗返回錯誤

上一章節我們是創建了一個線程,接下來我們創建多個線程

#include <iostream>
#include <string>
#include <pthread.h>
#include <unistd.h>
#include <vector>
#include <cstdio>using namespace std;void* start_routine(void* args )
{string name=static_cast<const char*>(args);//安全類型轉換while(true){cout<<"new thread create success, name: "<<name<<endl;sleep(1);}
}int main()
{//1.創建一批線程vector<pthread_t> tids;#define NUM 10for(int i=0;i<NUM;i++){pthread_t tid;char namebuffer[64];snprintf(namebuffer,sizeof namebuffer,"%s: %d","thread",i);//為每個線程設置編號// pthread_t id;//一旦創建成功,就執行上面的執行流pthread_create(&tid,nullptr,start_routine,(void*)namebuffer);}// //2.主執行流while(true){   cout<<"new thread create success, name: main thread"<<endl;sleep(1);}

?測試結果

🍉:從測試結果我們觀察到和我們預想的結果不一樣,接下來我們用下圖解釋

接下來我們對代碼進行一定修改?

 void* start_routine(void* args )
{sleep(1);ThreadData* td =static_cast<ThreadData*>(args);//安全類型轉換int cnt=10;while(cnt){cout<<"new thread create success, name: "<<td->namebuffer<<"cnt: "<<cnt--<<endl;sleep(1);}delete td;return nullptr;
}int main()
{//1.創建一批線程vector<ThreadData*> threads;#define NUM 10for(int i=0;i<NUM;i++){
/在這里我們通過new一個對象//ThreadData* td=new ThreadData();
///snprintf(td->namebuffer,sizeof (td->namebuffer),"%s: %d","thread",i+1);//為每個線程設置編號// pthread_t id;//一旦創建成功,就執行上面的執行流
///這里我們將地址td傳給pthread_create/pthread_create(&(td->tid),nullptr,start_routine,td);
保證了每一個執行流有自己獨立的new對象/threads.push_back(td);sleep(1);}}

🚢:start_routine這個函數現在被十個線程執行,這個函數現在?是重入狀態

這個函數是可重入函數嗎?答案是的,因為這個函數并沒有產生二義性。在函數內部定義的變量叫局部變量,具有臨時性。每個線程都有自己獨立的棧結構


?2.2pthread_self()獲取線程id

?該接口的作用是:獲取調用此接口的線程的id,并將id作為返回值。?


?3.線程終止

3.1.return 方式

exit() 能不能用來終止線程呢?答案是不能的,因為exit是終止進程的,任何一個執行流調用exit()都會讓整個進程退出。?接下來我們引入一個接口,用來終止線程。

3.2 pthread_exit?

🙂:我們在講到進程退出的時候,退出是有退出碼和退出信號的,為什么在線程這里線程退出的返回值是void 什么都沒有呢?

因為線程異常退出,也就是進程退出,所以退出信號是進程該關心的事。??

?4 線程等待

線程也是要被等待的,如果不等待,會造成類似僵尸進程的問題----------內存泄漏

線程等待:

1. 獲取線程的退出信息

2.回收新線程對應的PCB等內核資源,防止內存泄漏。

?pthread_join 接口

  for(auto& iter:threads)//遍歷threads{   //等待線程int n=pthread_join(iter->tid,nullptr);assert(n==0);cout<<"join: "<<iter->namebuffer<<"success"<<endl;delete iter;}cout<<"main thread quit"<<endl;

測試結果

??接下來我們對pthread_join(pthread_t thread, void **retval)第二個參數進行一下說明。

?

接下來我們對代碼做個簡單改變,讓大家明白第二個參數的使用,pthread?_join(pthread_tthread,void** retval)函數是如何獲取線程函數的返回結果的。

void* start_routine(void* args )
{ThreadData* td =static_cast<ThreadData*>(args);//安全類型轉換int cnt=10;while(cnt){// cout<<"cnt: "<<cnt <<"&cnt"<< &cnt<<endl;// cnt--;// sleep(1);cout<<"new thread create success, name: "<<td->namebuffer<<"cnt: "<<cnt--<<endl;sleep(1);}// delete td;
*******************這是我們的改動return (void*)2;//我們讓每個線程函數返回2
}
 for(auto& iter:threads)//遍歷threads{//我們想要獲取線程函數void*類型的返回結果,要設置一個void*變量void* ret=nullptr;//通過取地址&ret,來取到這個返回結果,所以為什么pthread_join()//第二個參數是void** 類型的,因為其是個輸出線參數。int n=pthread_join(iter->tid,&ret);assert(n==0);cout<<"join: "<<iter->namebuffer<<"success: "<<(long long)ret<<endl;delete iter;}

運行結果?

線程控制

創建線程-------->>>>>線程結束----------------->>>>>線程等待


?我們知道對于線程我們為了回收資源不造成內存泄漏,默認情況下都是要進行join的,但是對于我們需要關心線程返回值的情況,必須使用pthread_join()接口函數。如果我們并不關心該線程的返回值,那么其實我們可以不用手動回收線程,可以讓其系統自動回收,這就是線程分離?

pthread_detach()

該接口的作用是?將線程與主線程分離,主線程就不管該分離線程的返回值、退出和資源回收情況?。這個接口一般是線程自己調用或者主線程調用


三 理解線程tid?

我們在Linux: 線程概念初識-CSDN博客中說過??int n= pthread_create(&tid,nullptr,thread_routine,(void*)"thread_one");tid是個輸出型參數,這個tid的值并不是LWP的值。接下來我們就要對線程的id進行說明,為什么其是一個地址。

🚀:我們在線程概念初識這章節講過,每個線程都有自己獨立的棧結構,這個時候我們會有個疑問?無論有多少個線程,嚴格來說都在一個進程中,而一個進程有一份程序地址空間,也就是說只有一個棧結構,那么為什么說線程都有自己獨立的棧結構呢?

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

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

相關文章

避開養生誤區,擁抱健康生活

在追求健康的道路上&#xff0c;我們常常會陷入一些養生誤區&#xff0c;不僅無法達到預期效果&#xff0c;還可能損害身體健康。只有撥云見日&#xff0c;認清這些誤區&#xff0c;采取正確的養生方式&#xff0c;才能真正擁抱健康生活。? 很多人認為&#xff0c;保健品吃得…

<數據集>蘋果識別數據集<目標檢測>

數據集下載鏈接https://download.csdn.net/download/qq_53332949/90585216數據集格式&#xff1a;VOCYOLO格式 圖片數量&#xff1a;535張 標注數量(xml文件個數)&#xff1a;535 標注數量(txt文件個數)&#xff1a;535 標注類別數&#xff1a;2 標注類別名稱&#xff1a;…

【補題】P10424 [藍橋杯 2024 省 B] 好數(數位dp)

題意&#xff1a; 一個整數如果按從低位到高位的順序&#xff0c;奇數位&#xff08;個位、百位、萬位……&#xff09;上的數字是奇數&#xff0c;偶數位&#xff08;十位、千位、十萬位……&#xff09;上的數字是偶數&#xff0c;我們就稱之為“好數”。 給定一個正整數 N…

分布式存儲怎樣提高服務器數據的安全性?

分布式存儲是一種計算機數據存儲架構&#xff0c;主要是將數據信息分布存儲在多臺計算機或者是服務器上&#xff0c;以此來實現高可靠性、可擴展性和高性能&#xff0c;讓每個計算機或服務器可以通過網絡連接相互通信和協作。 分布式存儲系統會定期對重要的數據信息進行完整性檢…

數字IC后端培訓教程系列之PR Innovus工具寫出Calibre LVS用的Netlist詳細步驟

在數字IC后端設計實現chipfinish階段需要寫出很多數據&#xff0c;比如netlist&#xff0c;def&#xff0c;gds&#xff0c;lib和lef等文件。 今天給大家分享PR工具Innovus寫出Calibre物理驗證LVS要用的netlist的詳細步驟。 手把手教你debug解決物理驗證Calibre LVS錯誤 1&a…

TrueNAS scale(23.10) Restful API接口調用

背景 本文主要講解開源的NAS系統--TrueNAS的二次開發。 TrueNAS scale安裝 網上能找到很多類似的文章&#xff0c;本文就不介紹了&#xff0c;這里給一個視頻博主的傳送門&#xff1a; 司波圖 TrueNAS scale Resful API 接口 官網的 Resful API地址&#xff1a;TrueNAS REST…

卡爾曼濾波器淺聊

0 前言: 卡爾曼濾波屬于算法領域的,所以一些基本的數學概念是必須了解的 涉及到的數學基本概念 概念數學符號含義數學期望(Expected Value)E描述隨機變量平均取值的最核心概念概率(Probability)P(X= x i x_i xi?)隨機變量 X 取特定值 x i x_i xi?的概率方差(Varian…

1ll C++

在C++中,1ll 表示 long long 類型的整數常量1。這里的 ll 是 long long 的縮寫。這種寫法主要用于以下幾個方面: 1. 為什么需要 1ll? 在您的代碼中,1ll 主要用于 防止整數溢出 和 確保正確的類型轉換: cpp 復制 p = 1ll * p * i % MOD; f[i + 1] = 1ll * i * (i + 1) …

oracle 12c密碼長度,復雜度查看與設置

一 密碼長度和復雜度 Oracle 數據庫通過 PASSWORD_VERIFY_FUNCTION 來控制密碼復雜度。 1.1 查看當前的密碼復雜度設置 SELECT * FROM dba_profiles WHERE resource_name PASSWORD_VERIFY_FUNCTION; LIMIT表示分配給該 PROFILE 的密碼驗證函數名稱。如果為 NULL&#xff0c;…

指定運行級別

linux系統下有7種運行級別,我們需要來了解一下常用的運行級別,方便我們熟悉以后的部署環境,話不多說,來看. 開機流程&#xff1a; 指定數級別 基本介紹 運行級別說明: 0:關機 相當于shutdown -h now ??默認參數不能設置為0,否則系統無法正常啟動 1:單用戶(用于找回丟…

Appium工作原理及環境的搭建(1)

1、Appium的介紹&#xff1a; 一、什么是Appium Desktop&#xff1f; Appium Desktop是Appium項目的桌面版GUI工具&#xff0c;提供了一個友好的界面&#xff0c;用于啟動Appium服務器、查看設備日志、與設備交互、調試自動化腳本等。相比于命令行工具&#xff0c;Appium Des…

esp32cam遠程圖傳:AI Thinker ESP32-CAM -》 服務器公網 | 服務器 -》 電腦顯示

用AI Thinker ESP32-CAM板子訪問公網ip的5112端口并上傳你的攝像頭拍攝的圖像視頻數據&#xff0c;并寫一段python程序打開彈窗接受圖像實現超遠程圖像傳輸教程免費 1. 首先你要有一個公網ip也就是去買一臺擁有公網的服務器電腦&#xff0c;我買的是騰訊云1年38元的服務器還可…

【Pandas】pandas DataFrame copy

Pandas2.2 DataFrame Conversion 方法描述DataFrame.astype(dtype[, copy, errors])用于將 DataFrame 中的數據轉換為指定的數據類型DataFrame.convert_dtypes([infer_objects, …])用于將 DataFrame 中的數據類型轉換為更合適的類型DataFrame.infer_objects([copy])用于嘗試…

緩存相關問題

Redis 持久化機制 緩存雪崩、緩存穿透、緩存預熱、緩存更新、緩存降級等問題 熱點數據和冷數據是什么 Memcache與Redis的區別都有哪些? 單線程的redis為什么這么快 redis的數據類型,以及每種數據類型的使用場景,Redis 內部結構 redis的過期策略以及內存淘汰機制 Redis 為什么…

2025年AI開發學習路線

目錄 一、基礎階段&#xff08;2-3個月&#xff09; 1. 數學與編程基礎 2. 機器學習入門 二、核心技能&#xff08;3-4個月&#xff09; 1. 深度學習與框架 2. 大模型開發&#xff08;重點&#xff09; 三、進階方向&#xff08;3-6個月&#xff09; 1. 多模態與智能體…

SvelteKit 最新中文文檔教程(19)—— 最佳實踐之身份認證

前言 Svelte&#xff0c;一個語法簡潔、入門容易&#xff0c;面向未來的前端框架。 從 Svelte 誕生之初&#xff0c;就備受開發者的喜愛&#xff0c;根據統計&#xff0c;從 2019 年到 2024 年&#xff0c;連續 6 年一直是開發者最感興趣的前端框架 No.1&#xff1a; Svelte …

【Kafka基礎】消費者命令行完全指南:從基礎到高級消費

Kafka消費者是消息系統的關鍵組成部分&#xff0c;掌握/export/home/kafka_zk/kafka_2.13-2.7.1/bin/kafka-console-consumer.sh工具的使用對于調試、測試和監控都至關重要。本文將全面介紹該工具的各種用法&#xff0c;幫助您高效地從Kafka消費消息。 1 基礎消費模式 1.1 從最…

CausalML 基于機器學習算法的因果推理方法

CausalML 是一個 Python 包&#xff0c;它使用基于最新研究的機器學習算法提供一套提升建模和因果推理方法。它提供了一個標準界面&#xff0c;允許用戶從實驗或觀察數據中估計條件平均處理效應 &#xff08;CATE&#xff09;&#xff0c;也稱為個體治療效應 &#xff08;ITE&a…

解鎖深度學習激活函數

在深度學習的廣袤天地里&#xff0c;激活函數宛如隱匿于神經網絡架構中的神奇密碼&#xff0c;掌控著模型學習與表達的關鍵力量。今天&#xff0c;就讓我們一同深入探究這些激活函數的奇妙世界&#xff0c;揭開它們神秘的面紗。 一、激活函數為何不可或缺&#xff1f; 想象一…

從零到有的游戲開發(visual studio 2022 + easyx.h)

引言 本文章適用于C語言初學者掌握基本的游戲開發&#xff0c; 我將用詳細的步驟引領大家如何開發屬于自己的游戲。 作者溫馨提示&#xff1a;不要認為開發游戲很難&#xff0c;一些基本的游戲邏輯其實很簡單&#xff0c; 關于游戲的開發環境也不用擔心&#xff0c;我會詳細…