【回眸】Linux 內核 (十五) 之 多線程編程 上

前言

進程和線程 區別

線程API

1.創建線程

2.線程退出?

3.線程等待

4.線程脫離

5.?線程ID獲取及比較?

6.創建及銷毀互斥鎖

7.創建及銷毀條件變量

?8.?等待

9.觸發

多線程編程?

后記

前言

高產的幾天。

進程和線程 區別

進程——資源分配的最小單位,線程——程序執行的最小單位

進程有獨立的地址空間,線程沒有單獨的地址空間(同一進程內的線程共享進程的地址空間)。

線程API

多線程開發在 Linux 平臺上已經有成熟的 pthread 庫支持。其涉及的多線程開發的最基本概念主要包含三點:線程,互斥鎖,條件。其中,線程操作又分線程的創建,退出,等待 3 種。互斥鎖則包括 4 種操作,分別是創建,銷毀,加鎖和解鎖。條件操作有 5 種操作:創建,銷毀,觸發,廣播和等待。

1.創建線程

#include <pthread.h>
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
// 返回:若成功返回0,否則返回錯誤編號

2.線程退出?

#include <pthread.h>
int pthread_exit(void *rval_ptr);

3.線程等待

#include <pthread.h>
int pthread_join(pthread_t thread, void **rval_ptr);
// 返回:若成功返回0,否則返回錯誤編號

4.線程脫離

#include <pthread.h>
int pthread_detach(pthread_t thread);
// 返回:若成功返回0,否則返回錯誤編號

5.?線程ID獲取及比較?

#include <pthread.h>
pthread_t pthread_self(void);
// 返回:調用線程的ID
#include <pthread.h>
int pthread_equal(pthread_t tid1, pthread_t tid2);
// 返回:若相等則返回非0值,否則返回0

6.創建及銷毀互斥鎖

#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t mutex);
// 返回:若成功返回0,否則返回錯誤編號
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex)
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
// 返回:若成功返回0,否則返回錯誤編號

7.創建及銷毀條件變量

#include <pthread.h>
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t cond);
// 返回:若成功返回0,否則返回錯誤編號

?8.?等待

#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, cond struct timespec *restrict timeout);
// 返回:若成功返回0,否則返回錯誤編號

9.觸發

#include <pthread.h>
int pthread_cond_signal(pthread_cond_t cond);
int pthread_cond_broadcast(pthread_cond_t cond);
// 返回:若成功返回0,否則返回錯誤編號

多線程編程?

thread1.c(線程創建)

#include <stdio.h>
#include <pthread.h>void *func1(void *arg){printf("t1:%ld thread is created.\n",(unsigned long)pthread_self());
printf("t1:param is %d\n",*((int *)arg));}int main(){
int ret;
int param =100;
pthread_t t1;
ret = pthread_create(&t1,NULL,func1,(void *)&param);
if(ret == 0){
printf("main:Create t1 sucess.\n");
}
printf("mainID:%ld .\n",(unsigned long)pthread_self());
while(1);return 0;
}

thread2.c(等待和退出,傳整數)

#include <stdio.h>
#include <pthread.h>void *func1(void *arg){
static int ret = 10;
printf("t1:%ld thread is created.\n",(unsigned long)pthread_self());
printf("t1:param is %d\n",*((int *)arg));
pthread_exit((void *)&ret);}int main(){
int ret;
int param =100;
int *pret;
pthread_t t1;
ret = pthread_create(&t1,NULL,func1,(void *)&param);
if(ret == 0){
printf("main:Create t1 sucess.\n");
}
printf("mainID:%ld .\n",(unsigned long)pthread_self());
//while(1);
pthread_join(t1,(void **)&pret);
printf("main:t1 exit. ret = %d\n", *pret);
return 0;
}

thread3.c(等待和退出 傳字符串)?

#include <stdio.h>
#include <pthread.h>void *func1(void *arg){
static char *p = "t1 pijiuya1 is runing.\n";
printf("t1:%ld thread is created.\n",(unsigned long)pthread_self());
printf("t1:param is %d\n",*((int *)arg));
pthread_exit((void *)p);//退出}int main(){
int ret;
int param =100;
char *pret = NULL;
pthread_t t1;
ret = pthread_create(&t1,NULL,func1,(void *)&param);
if(ret == 0){
printf("main:Create t1 sucess.\n");
}
printf("mainID:%ld .\n",(unsigned long)pthread_self());
//while(1);
pthread_join(t1,(void **)&pret);//等待
printf("main:t1 exit. ret = %s\n", pret);
return 0;
}

thread4.c(創建2個)

#include <stdio.h>
#include <pthread.h>void *func1(void *arg){
static int ret = 10;
printf("t1:%ld thread is created.\n",(unsigned long)pthread_self());
printf("t1:param is %d\n",*((int *)arg));
pthread_exit((void *)&ret);}int main(){
int ret;
int param =100;
int *pret;
pthread_t t1;
ret = pthread_create(&t1,NULL,func1,(void *)&param);
if(ret == 0){
printf("main:Create t1 sucess.\n");
}
printf("mainID:%ld .\n",(unsigned long)pthread_self());
//while(1);
pthread_join(t1,(void **)&pret);
printf("main:t1 exit. ret = %d\n", *pret);
return 0;
}

?thread5.c(創建2個且打印順序發現多線程共享同一段內存【順序沒有重復】)

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>int g_data = 0;
void *func1(void *arg){printf("t1:%ld thread is created.\n",(unsigned long)pthread_self());
printf("t1:param is %d\n",*((int *)arg));
while(1){
printf("t1:%d\n",g_data++);
sleep(1);
};}
void *func2(void *arg){
printf("t2:%ld thread is created.\n",(unsigned long)pthread_self());
printf("t2:param is %d\n",*((int *)arg));
while(1){
printf("t2:%d\n",g_data++);
sleep(1);
};}
int main(){
int ret;
int param =100;
pthread_t t1;
pthread_t t2;
ret = pthread_create(&t1,NULL,func1,(void *)&param);
if(ret == 0){
printf("main:Create t1 sucess.\n");
}
printf("mainID:%ld .\n",(unsigned long)pthread_self());
ret = pthread_create(&t2,NULL,func2,(void *)&param);
if(ret == 0){
printf("main:Create t2 sucess.\n");
}
printf("mainID:%ld .\n",(unsigned long)pthread_self());
while(1){
printf("main:%d\n",g_data++);
sleep(1);
};
pthread_join(t1,NULL);//等待
pthread_join(t2,NULL);//等待
return 0;
}

?

搶占資源是隨機的,每次運行的結果不盡相同。

thread6.c(創建3個線程并且加鎖,讓t1優先運行且不被t2 t3 打斷,t1 釋放鎖后,t3和t2競爭資源)

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>pthread_mutex_t mutex;
pthread_attr_t attr;
void *func1(void *arg){
int i ;
pthread_mutex_lock(&mutex);//保證t1優先
for(i = 0;i<5;i++){
printf("t1:%ld thread is created.\n",(unsigned long)pthread_self());
printf("t1:param is %d\n",*((int *)arg));
}
pthread_mutex_unlock(&mutex);}
void *func2(void *arg){
pthread_mutex_lock(&mutex);
printf("t2:%ld thread is created.\n",(unsigned long)pthread_self());
printf("t2:param is %d\n",*((int *)arg));
pthread_mutex_unlock(&mutex);
}
void *func3(void *arg){
pthread_mutex_lock(&mutex);
printf("t3:%ld thread is created.\n",(unsigned long)pthread_self());
printf("t3:param is %d\n",*((int *)arg));
pthread_mutex_unlock(&mutex);
}
int main(){
int ret;
int param =100;
pthread_t t1;
pthread_t t2;
pthread_t t3;
pthread_mutex_init(&mutex,NULL);
ret = pthread_create(&t1,NULL,func1,(void *)&param);
if(ret == 0){
printf("main:Create t1 sucess.\n");
}
ret = pthread_create(&t2,NULL,func2,(void *)&param);
if(ret == 0){
printf("main:Create t2 sucess.\n");
}
ret = pthread_create(&t3,NULL,func3,(void *)&param);
if(ret == 0){
printf("main:Create t3 sucess.\n");
}
printf("mainID:%ld .\n",(unsigned long)pthread_self());pthread_join(t1,NULL);//等待
pthread_join(t2,NULL);//等待
pthread_join(t3,NULL);//等待
pthread_attr_destroy(&attr);
return 0;
}

?

?thread7.c(fun1先運行到10退出鎖,func2后運行不退出)

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>pthread_mutex_t mutex;
pthread_attr_t attr;
int g_data = 0;
void *func1(void *arg){
pthread_mutex_lock(&mutex);//保證t1優先
while(1){
printf("t1:%d\n",g_data++);
sleep(1);
if (g_data == 10){
pthread_mutex_unlock(&mutex);
pthread_exit(NULL);
}
}}
void *func2(void *arg){printf("t2:%ld thread is created.\n",(unsigned long)pthread_self());
printf("t2:param is %d\n",*((int *)arg));
while(1){
pthread_mutex_lock(&mutex);
printf("t2:%d\n",g_data);
g_data++;
pthread_mutex_unlock(&mutex);
sleep(1); 
}
}
int main(){
int ret;
int param =100;
pthread_t t1;
pthread_t t2;
pthread_mutex_init(&mutex,NULL);
ret = pthread_create(&t1,NULL,func1,(void *)&param);
if(ret == 0){
printf("main:Create t1 sucess.\n");
}
ret = pthread_create(&t2,NULL,func2,(void *)&param);
if(ret == 0){
printf("main:Create t2 sucess.\n");
}
printf("mainID:%ld .\n",(unsigned long)pthread_self());
printf("main:g_data = %d.\n",g_data);
pthread_join(t1,NULL);//等待
pthread_join(t2,NULL);//等待
pthread_attr_destroy(&attr);
return 0;
}

后記

內容實在是有點多,故而分兩篇博文。這個多線程的內容在Java里代碼很少,回顧了linux這里的互斥鎖,感受更加不一樣,比當時更加理解了互斥鎖的問題。

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

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

相關文章

127.0.0.1本地環回地址(Loopback Address)

127.0.0.1 是計算機網絡中的一個特殊IPv4地址&#xff0c;稱為本地環回地址&#xff08;Loopback Address&#xff09;&#xff0c;主要用于以下用途&#xff1a; 1. 基本定義 本地主機&#xff08;Localhost&#xff09;&#xff1a;該地址始終指向當前正在使用的計算機本身&a…

S7-1200 PLC熱電偶和熱電阻模擬量模塊

熱電偶和熱電阻模擬量模塊 S7-1200 PLC有專用用于對溫度進行采集的熱電偶模塊SM1231 TC和SM 1231RTD。熱電偶模塊有4AI和8AI兩種&#xff0c;下面以SM1231 TC 4AI為例看一下接線圖。 該模塊一共有4個通道&#xff0c;每個通道有兩個接線端子&#xff0c;比如0&#xff0c;0-。…

深度了解向量引論

今天去研究了一個基本數學原理 這個其實需要證明 今天推導了一下這個公式&#xff0c;感覺收獲挺大 下面是手工推導過程

Feign修仙指南:聲明式HTTP請求的優雅之道

各位在微服務世界摸爬滾打的道友們&#xff01;今天要解鎖的是Spring Cloud的絕世神通——Feign&#xff01;這貨堪稱HTTP界的"言出法隨"&#xff0c;只需定義接口&#xff0c;就能自動生成HTTP請求代碼&#xff01;從此告別手動拼裝URL的苦日子&#xff0c;讓你的代…

UDP學習筆記(四)UDP 為什么大小不能超過 64KB?

&#x1f310; UDP 為什么大小不能超過 64KB&#xff1f;TCP 有這個限制嗎&#xff1f; 在進行網絡編程或者調試網絡協議時&#xff0c;我們常常會看到一個說法&#xff1a; “UDP 最大只能發送 64KB 數據。” 這到底是怎么回事&#xff1f;這 64KB 是怎么來的&#xff1f;TCP…

LabVIEW 中串口設備與采集卡的同步精度

在 LabVIEW 項目開發中&#xff0c;常涉及多種設備協同工作&#xff0c;如通過串口設備采集溫度&#xff0c;利用采集卡&#xff08;如 NI 6251&#xff09;采集壓力。此時&#xff0c;設備間的同步精度至關重要&#xff0c;它直接影響系統數據的準確性與可靠性。下面&#xff…

DP_AUX輔助通道介紹

DisplayPort&#xff08;簡稱DP&#xff09;是一個由PC及芯片制造商聯盟開發&#xff0c;視頻電子標準協會&#xff08;VESA&#xff09;標準化的數字式視頻接口標準。該接口免認證、免授權金&#xff0c;主要用于視頻源與顯示器等設備的連接&#xff0c;并也支持攜帶音頻、USB…

[GESP202312 五級] 平均分配

文章目錄 題目描述輸入格式輸出格式輸入輸出樣例 #1輸入 #1輸出 #1 輸入輸出樣例 #2輸入 #2輸出 #2 提交鏈接提示解析參考代碼 題目描述 小楊認為&#xff0c;所有大于等于 a a a 的完全平方數都是他的超級幸運數。 小楊還認為&#xff0c;所有超級幸運數的倍數都是他的幸運…

[Mysql]buffersize修改

1、找到my.cnf文件位置 ps -ef|grep mysqld 2、編輯my.cnf cd /etc/my.cnf.d vim my.cnf 一般修改為內存的50%~70% 3、重啟服務 systemctl restart mysqld

清晰易懂的 Apollo 配置中心安裝與使用教程

Apollo 是攜程開源的分布式配置管理平臺&#xff0c;支持配置實時推送、版本管理、權限控制等功能。本教程將手把手教你完成 Apollo 核心組件安裝、基礎配置管理及避坑指南&#xff0c;助你快速掌握企業級配置管理能力。 一、環境準備&#xff08;關鍵依賴&#xff09; 1. 基礎…

PyTorch池化層詳解:原理、實現與示例

池化層&#xff08;Pooling Layer&#xff09;是卷積神經網絡中的重要組成部分&#xff0c;主要用于降低特征圖的空間維度、減少計算量并增強模型的平移不變性。本文將通過PyTorch代碼演示池化層的實現原理&#xff0c;并詳細講解最大池化、平均池化、填充&#xff08;Padding&…

如何構建并優化提示詞?

提示詞是一個小白最容易上手大模型的方式&#xff0c;提示詞就是你告訴大模型應該如何去完成一項工作的系統性的命令&#xff0c;所以寫一個好的提示詞是比較關鍵的&#xff0c;那么如何寫好一個提示詞呢&#xff1f; 要寫好提示詞&#xff0c;其實就像我們要把一些命令清晰地傳…

面向大模型的開發框架LangChain

這篇文章會帶給你 如何使用 LangChain&#xff1a;一套在大模型能力上封裝的工具框架如何用幾行代碼實現一個復雜的 AI 應用面向大模型的流程開發的過程抽象 文章目錄 這篇文章會帶給你寫在前面LangChain 的核心組件文檔&#xff08;以 Python 版為例&#xff09;模型 I/O 封裝…

【藍橋杯】動態規劃:線性動態規劃

1. 最長上升子序列(LIS) 1.1. 題目 想象你有一排數字,比如:3, 1, 2, 1, 8, 5, 6 你要從中挑出一些數字,這些數字要滿足兩個條件: 你挑的數字的順序要和原來序列中的順序一致(不能打亂順序) 你挑的數字要一個比一個大(嚴格遞增) 問:最多能挑出多少個這樣的數字? …

vue2和vue3的主要區別

一、性能優化與響應式系統 性能優化&#xff1a; Vue2&#xff1a;性能較好&#xff0c;但在大型應用中&#xff0c;當數據變化頻繁時可能出現性能瓶頸。它使用虛擬DOM來高效地進行DOM操作&#xff0c;并通過多種技術手段如懶加載、異步組件、樹形抖動等優化性能。 Vue3&…

Python: 實現數據可視化分析系統

后端基于Python 開源的 Web 框架 Flask&#xff0c;前端頁面采用 LayUI 框架以及 Echarts 圖表&#xff0c;數據庫為sqlite。系統的功能模塊分為數據采集和存儲模塊、數據處理和分析模塊、可視化展示模塊和系統管理模塊。情感分析方面使用LDA等主題建模技術&#xff0c;結合領域…

深度學習總結(3)

數據批量的概念 通常來說&#xff0c;深度學習中所有數據張量的第一個軸&#xff08;也就是軸0&#xff0c;因為索引從0開始&#xff09;都是樣本軸[samples axis&#xff0c;有時也叫樣本維度&#xff08;samples dimension&#xff09;?]?。深度學習模型不會一次性處理整個…

微軟慶祝它成立整整50周年

每周跟蹤AI熱點新聞動向和震撼發展 想要探索生成式人工智能的前沿進展嗎&#xff1f;訂閱我們的簡報&#xff0c;深入解析最新的技術突破、實際應用案例和未來的趨勢。與全球數同行一同&#xff0c;從行業內部的深度分析和實用指南中受益。不要錯過這個機會&#xff0c;成為AI領…

【操作系統(Linux)】——通過案例學習父子進程的線程異步性

本篇旨在通過幾個案例來學習父子進程的線程異步性 一、父進程與子進程 我們將要做的&#xff1a; 創建父子進程&#xff0c;觀察父子進程執行的順序&#xff0c;了解進程執行的異步行為 源代碼&#xff1a; #include <stdio.h> #include <sys/types.h> #include…

系統性能核心指標:QPS、TPS、RT、并發量詳解

系統性能核心指標&#xff1a;QPS、TPS、RT、并發量詳解 1. 引言 在分布式系統、高并發架構設計中&#xff0c;QPS、TPS、RT、并發量 等指標是衡量系統性能的關鍵。本文深入解析這些術語的定義、計算方法、關聯性及優化策略&#xff0c;幫助開發者更好地進行系統性能評估與調…