pthread_self函數
獲取線程ID。其作用對應進程中 getpid() 函數。
?????? pthread_t pthread_self(void);????? 返回值:成功:0;???? 失敗:無!
?????? 線程ID:pthread_t類型,本質:在Linux下為無符號整數(%lu),其他系統中可能是結構體實現
?????? 線程ID是進程內部,識別標志。(兩個進程間,線程ID允許相同)
?????? 注意:不應使用全局變量 pthread_t tid,在子線程中通過pthread_create傳出參數來獲取線程ID,而應使用pthread_self。
pthread_create函數
創建一個新線程。???????????? 其作用,對應進程中fork() 函數。
?????? int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
?????? 返回值:成功:0;???? 失敗:錯誤號????? -----Linux環境下,所有線程特點,失敗均直接返回錯誤號。
參數:??
?????? pthread_t:當前Linux中可理解為:typedef? unsigned long int? pthread_t;
參數1:傳出參數,保存系統為我們分配好的線程ID
?????? 參數2:通常傳NULL,表示使用線程默認屬性。若想使用具體屬性也可以修改該參數。
?????? 參數3:函數指針,指向線程主函數(線程體),該函數運行結束,則線程結束。
?????? 參數4:線程主函數執行期間所使用的參數。
在一個線程中調用pthread_create()創建新的線程后,當前線程從pthread_create()返回繼續往下執行,而新的線程所執行的代碼由我們傳給pthread_create的函數指針start_routine決定。start_routine函數接收一個參數,是通過pthread_create的arg參數傳遞給它的,該參數的類型為void *,這個指針按什么類型解釋由調用者自己定義。start_routine的返回值類型也是void *,這個指針的含義同樣由調用者自己定義。start_routine返回時,這個線程就退出了,其它線程可以調用pthread_join得到start_routine的返回值,類似于父進程調用wait(2)得到子進程的退出狀態,稍后詳細介紹pthread_join。
pthread_create成功返回后,新創建的線程的id被填寫到thread參數所指向的內存單元。我們知道進程id的類型是pid_t,每個進程的id在整個系統中是唯一的,調用getpid(2)可以獲得當前進程的id,是一個正整數值。線程id的類型是thread_t,它只在當前進程中保證是唯一的,在不同的系統中thread_t這個類型有不同的實現,它可能是一個整數值,也可能是一個結構體,也可能是一個地址,所以不能簡單地當成整數用printf打印,調用pthread_self(3)可以獲得當前線程的id。
attr參數表示線程屬性,本節不深入討論線程屬性,所有代碼例子都傳NULL給attr參數,表示線程屬性取缺省值,感興趣的讀者可以參考APUE。
【練習】:創建一個新線程,打印線程ID。注意:鏈接線程庫 -lpthread? ???????????????????? ???????????????????? 【pthrd_crt.c】
由于pthread_create的錯誤碼不保存在errno中,因此不能直接用perror(3)打印錯誤信息,可以先用strerror(3)把錯誤碼轉換成錯誤信息再打印。如果任意一個線程調用了exit或_exit,則整個進程的所有線程都終止,由于從main函數return也相當于調用exit,為了防止新創建的線程還沒有得到執行就終止,我們在main函數return之前延時1秒,這只是一種權宜之計,即使主線程等待1秒,內核也不一定會調度新創建的線程執行,下一節我們會看到更好的辦法。
【練習】:循環創建多個線程,每個線程打印自己是第幾個被創建的線程。(類似于進程循環創建子進程)? ??????????????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????? ?? ? 【more_pthrd.c】
拓展思考:將pthread_create函數參4修改為(void *)&i, 將線程主函數內改為 i=*((int *)arg) 是否可以?
/*** pthread_create.c ***/ #include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<pthread.h> #include<string.h> void *thrd_func(void *arg) {printf("In thread : thread id = %lu,pid = %u\n",pthread_self(),getpid());return NULL;}int main() {pthread_t tid;int ret;printf("In main 1 : thread id = %lu,pid = %ui\n",pthread_self(),getpid());ret = pthread_create(&tid,NULL,thrd_func,NULL);if(0 != ret){fprintf(stderr,"pthread_create error:%s\n",strerror(ret));exit(1); }sleep(1);printf("In main 2 : thread id = %lu,pid = %u\n",pthread_self(),getpid());return 0; }
運行結果:
ubuntu1604@ubuntu:~/wangqinghe/linux/20190814$ ./pthread_create
In main 1 : thread id = 140573795596032,pid = 3648i
In thread : thread id = 140573787256576,pid = 3648
In main 2 : thread id = 140573795596032,pid = 3648
?
循環創建多個子線程 /*** mul_pthread.c ***/ #include<stdio.h> #include<string.h> #include<unistd.h> #include<pthread.h> #include<stdlib.h>void *thrd_func(void *arg) {int i = (int)arg;sleep(i);printf("%dth thread: thread id = %lu,pid = %u\n",i+1,pthread_self(),getpid());return NULL; }int main() {pthread_t tid;int ret,i;for(i = 0; i < 5; i++){ret = pthread_create(&tid,NULL,thrd_func,(void *)i);if(0 != ret){fprintf(stderr,"pthrea_create error:%s\n",strerror(ret));exit(1);}}sleep(i);return 0; }
運行結果:
ubuntu1604@ubuntu:~/wangqinghe/linux/20190814$ ./mul_pthread
1th thread: thread id = 140132717160192,pid = 4026
2th thread: thread id = 140132708767488,pid = 4026
3th thread: thread id = 140132700374784,pid = 4026
4th thread: thread id = 140132691982080,pid = 4026
5th thread: thread id = 140132683589376,pid = 4026
?