<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
執行緒是程序內部的一條執行序列或執行路徑,一個程序可以包含多條執行緒。
執行序列就是一組有序指令的集合——函數。
執行緒是程序內部的一條執行序列,一個程序至少有一條執行緒,稱之為主執行緒(main方法代表的執行序列),可以通過執行緒庫建立其他執行緒(給執行緒制定一個它要執行的函數),將建立的執行緒稱之為函數執行緒。
Linux 實現執行緒的機制非常獨特。從核心的角度來說,它並沒有執行緒這個概念。
Linux 把所有的執行緒都當做程序來實現。核心並沒有準備特別的排程演演算法或是定義特別的資料結構來表徵執行緒。
相反,執行緒僅僅被視為一個與其他程序共用某些資源的程序。
每個執行緒都擁有唯 一隸屬於自己的task_struct,所以在核心中,它看起來就像是一個普通的程序(只是執行緒和 其他一些程序共用某些資源,如地址空間)
1.建立執行緒
#include<phread.h> int pthread_create(pthread_t *id , pthread_attr_t *attr, void(*fun)(void*), void *arg);
id
:傳遞一個pthread_t型別的變數的地址,建立成功後,用來獲取新建立的執行緒的TIDattr
:指定執行緒的屬性 預設使用NULLfun
:執行緒函數的地址arg
:傳遞給執行緒函數的引數多執行緒程式碼範例
#include<stdio.h> #include<stdlib.h> #include<assert.h> #include<string.h> #include<unistd.h> #include<pthread.h> //宣告一個執行緒函數 void *fun(void *); int main() { printf("main startn"); pthread_t id; //建立函數執行緒,並且指定函數執行緒要執行的函數 int res = pthread_create(&id,NULL,fun,NULL); assert(res == 0); //之後並行執行 int i = 0; for(; i < 5; i++) { printf("main runningn"); sleep(1); } printf("main overn"); exit(0); } //定義執行緒函數 void* fun(void *arg) { printf("fun startn"); int i = 0; for(; i < 3;i++) { printf("fun runningn"); sleep(1); } printf("fun overn"); }
gcc編譯程式碼時報`undifined reference to xxxxx錯誤,都是因為程式中呼叫了一些方法,但是沒有連線該方法所在的檔案,例如下面的情況:
連線庫檔案編譯成功並執行,這一點在幫助手冊中也有提示:Compile and link with -pthread
比較兩次執行的結果發現前三條執行語句時一樣的
結論
函數執行緒在主執行緒結束後也隨之退出,原因:主執行緒結束時使用的是exit方法,這個方法結束的是程序。
然而修改程式碼為:pthread_exit(NULL);
此時主執行緒結束,函數執行緒會繼續執行直至完成。即便如此,我們還是不推薦大家手動結束主執行緒,我們更喜歡讓主執行緒等待一會。
給執行緒函數傳參
①值傳遞
將變數的值直接轉成void*型別進行傳遞
因為執行緒函數接受的是一個void*型別的指標,只要是指標,32位元系統上都是4個位元組,值傳遞就只能傳遞小於或等於4位元組的值。
程式碼範例
#include<stdio.h> #include<stdlib.h> #include<assert.h> #include<string.h> #include<unistd.h> #include<pthread.h> void *fun(void *); int main() { printf("main startn"); int a = 10; pthread_t id; int res = pthread_create(&id,NULL,fun,(void*)a); assert(res == 0); int i = 0; for(; i < 5; i++) { printf("main runningn"); sleep(1); } printf("main overn"); exit(0); } void* fun(void *arg) { int b = (int)arg; printf("b == %dn",b); }
②地址傳遞
將變數(所有型別)的地址強轉成void*
型別進行傳遞,就和在普通函數呼叫傳遞變數的地址相似。
主執行緒和函數執行緒通過這個地址就可以共用地址所指向的空間。
一個程序內的所有執行緒是共用這個程序的地址空間。
多執行緒下程序的4G虛擬地址空間
一個程序內的所有執行緒對於全域性資料,靜態資料,堆區空間都是共用的。
執行緒之間傳遞資料很簡單,但是隨之帶來的問題就是執行緒並行執行時無法保證執行緒安全。
程式碼範例
#include<stdio.h> #include<stdlib.h> #include<assert.h> #include<string.h> #include<unistd.h> #include<pthread.h> int gdata = 10; //.data void *fun(void *); int main() { int *ptr = (int *)malloc(4);//.heap *ptr = 10; pthread_t id; int res = pthread_create(&id,NULL,fun,(void*)ptr); assert(res == 0); sleep(2);//等待兩秒,保證函數執行緒已經講資料修改 printf("main : gdata == %dn",gdata); printf("main : *ptr = %dn",*ptr); exit(0); } void *fun(void *arg) { int *p = (int*)arg; gdata = 20000; *p = 20; printf("fun overn"); }
執行緒退出的三種方式:
等待執行緒終止
int pthread_join(pthread_t thread, void **retval); args: pthread_t thread: 被連線執行緒的執行緒號,該執行緒必須位於當前程序中,而且不得是分離執行緒 void **retval :該引數不為NULL時,指向某個位置 在該函數返回時,將該位置設定為已終止執行緒的退出狀態 return: 執行緒連線的狀態,0是成功,非0是失敗
當A執行緒呼叫執行緒B並 pthread_join() 時,A執行緒會處於阻塞狀態,直到B執行緒結束後,A執行緒才會繼續執行下去。當 pthread_join() 函數返回後,被呼叫執行緒才算真正意義上的結束,它的記憶體空間也會被釋放(如果被呼叫執行緒是非分離的)。
這裡有三點需要注意:
等待指定的子執行緒結束
int pthread_join(pthread_t id,void **result)//呼叫這個方法的執行緒會阻塞,直到等待執行緒結束
程式碼演示:
#include<stdio.h> #include<stdlib.h> #include<assert.h> #include<string.h> #include<unistd.h> #include<pthread.h> int main() { printf("main startn"); pthread_t id; int res = pthread_create(&id,NULL,fun,NULL); assert(res == 0); //之後並行執行 int i = 0; for(; i < 5; i++) { printf("main runningn"); sleep(1); } char *s = NULL; pthread_join(id,(void **)&s); printf("join : s = %sn",s); exit(0); } //定義執行緒函數 void* fun(void *arg) { printf("fun startn"); int i = 0; for(; i < 10;i++) { printf("fun runningn"); sleep(1); } printf("fun overn"); pthread_exit("fun over");//將該字元常數返回給主執行緒 }
此時,主執行緒完成五次輸出,就會等待子執行緒結束,阻塞等待,子執行緒結束後,最後,主執行緒列印join:s = fun over
關於exit和join的一些詳細說明:
執行緒具有的屬性可以線上程建立的時候指定;
——pthread_create()函數的第二個引數(pthread_attr_t *attr)表示執行緒的屬性,在以前的例子中將其值設為NULL,也就是採用預設屬性,執行緒的多項屬性都是可以修改的,這些屬性包括繫結屬性,分離屬性,堆疊屬性,堆疊大小,優先順序。
系統預設的是非繫結,非分離,預設1M的堆疊以及父子程序優先順序相同
執行緒結構如下:
typedef struct { int detachstate; //執行緒的分離狀態 int schedpolicy; //執行緒排程策略 struct sched_param schedparam; //執行緒的排程引數 int inheritsched; //執行緒的繼承性 int scope; //執行緒的作用域 size_t guardsize; //執行緒棧末尾的警戒緩衝區大小 int stackaddr_set; //執行緒的棧設定 void* stackaddr; //執行緒棧的位置 size_t stacksize; //執行緒棧的大小 } pthread_attr_t;
每一個屬性都有對應的一些函數,用於對其進行檢視和修改,下面分別介紹:
初始化和去初始化分別對應於如下的兩個函數:
#include <pthread.h> ①int pthread_attr_init(pthread_attr_t *attr); ②it pthread_attr_destroy(pthread_attr_t *attr);
①功能:
引數:
attr
:執行緒屬性結構體返回值:
②功能:
引數:
attr
:執行緒屬性結構體返回值:
執行緒的分離狀態決定一個執行緒以什麼樣的方式來終止自己,這個在之前我們也說過了。
相關API如下:
#include <pthread.h> int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
功能:設定執行緒分離狀態
引數:
attr
:已初始化的執行緒屬性detachstate
: 分離狀態PTHREAD_CREATE_DETACHED(分離執行緒)
PTHREAD_CREATE_JOINABLE(非分離執行緒)
返回值:
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
功能:獲取執行緒分離狀態
引數:
attr
:已初始化的執行緒屬性detachstate: 分離狀態PTHREAD_CREATE_DETACHED(分離執行緒)
PTHREAD _CREATE_JOINABLE(非分離執行緒)
返回值:
注意:
當一個執行緒被設定為分離執行緒時,假設此時該執行緒的執行速度非常快,它很可能在pthread_create返回之前就終止; 終止之後將執行緒號和系統資源移交給其他執行緒使用,這樣呼叫create就得到了錯誤的執行緒號,因此就必須採取一些同步措施,可以在被建立的執行緒裡呼叫pthread_cond_timedwait函數,讓這個執行緒等待一會兒,留出足夠的時間讓函數pthread_create返回,設定一段等待時間,是在多執行緒程式設計裡常用的方法。但是注意不要使用諸如wait()之類的函數,它們是使整個程序睡眠,並不能解決執行緒同步的問題。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45