【Linux系统编程】线程的基本操作
概述
每個進程都擁有自己的數據段、代碼段和堆棧段,這就造成進程在進行創建、切換、撤銷操作時,需要較大的系統開銷。為了減少系統開銷,從進程中演化出了線程。為了讓進程完成一定的工作,進程必須至少包含一個線程。線程存在于進程中,共享進程的資源。更多詳情,請看《進程和線程的區別與聯系》。
?
就像每個進程都有一個進程號一樣,每個線程也有一個線程號。進程號在整個系統中是唯一的,但線程號不同,線程號只在它所屬的進程環境中有效。進程號用 pid_t 數據類型表示,是一個非負整數。線程號則用 pthread_t 數據類型來表示,Linux 使用無符號長整數表示。有的系統在實現 pthread_t 的時候,用一個結構體來表示,所以在可移植的操作系統實現不能把它做為整數處理。
?
線程的常用函數
1)獲取線程號
所需頭文件:
#include <pthread.h>
?
pthread_t pthread_self(void);
功能:
獲取線程號。
參數:
無
返回值:
調用線程的線程 ID 。
?
2)線程號的比較
?
所需頭文件:
#include <pthread.h>
?
int pthread_equal(pthread_t t1, pthread_t t2);
?
功能:
判斷線程號 t1 和 t2 是否相等。為了方便移植,盡量使用函數來比較線程 ID。
參數:
t1,t2:待判斷的線程號。
返回值:
相等: ?非 0
不相等:0
?
示例代碼:
#include <stdio.h> #include <stdlib.h> #include <pthread.h>int main(int argc, char *argv[]) {pthread_t thread_id;thread_id = pthread_self(); // 返回調用線程的線程IDprintf("Thread ID = %lu \n",thread_id);if( 0 != pthread_equal( thread_id, pthread_self() ) ){printf("Equal!\n");}else{printf("Not equal!\n");}return 0; }?
線程函數的程序在 pthread 庫中,故鏈接時要加上參數 -lpthread。
?
?
?
?
運行結果如下:
?
3)線程的創建
所需頭文件:
#include <pthread.h>
?
int pthread_create( pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine)(void *),
void *arg );
功能:
創建一個線程。
參數:
thread:線程標識符地址。
attr:線程屬性結構體地址,通常設置為 NULL。
start_routine:線程函數的入口地址。
arg:傳給線程函數的參數。
返回值:
成功:0
失敗:非 0
?
pthread_create() 創建的線程從指定的回調函數開始運行,該函數運行完后,該線程也就退出了。線程依賴進程存在的,共享進程的資源,如果創建線程的進程結束了,線程也就結束了。
?
示例一:
?
#include <stdio.h> #include <unistd.h> #include <pthread.h>int var = 8;void *thread_1(void *arg) {while(1){printf("this is my new thread1: var++\n");var++;sleep(1);}return NULL; }void *thread_2(void * arg) {while(1){printf("this is my new thread2: var = %d\n", var);sleep(1);}return NULL; }int main(int argc, char *argv[]) {pthread_t tid1,tid2;//創建兩個線程pthread_create(&tid1, NULL, thread_1, NULL); pthread_create(&tid2, NULL, thread_2, NULL);while(1){printf("the main thread: var = %d\n", var);sleep(1);}return 0; }?
?
?
?
?
?
運行結果如下:
?
?
示例二:
?
#include <stdio.h> #include <unistd.h> #include <pthread.h>// 回調函數 void *thread_fun(void * arg) {sleep(1);int num = *( (int *)arg );printf("int the new thread: num = %d\n", num);return NULL; }int main(int argc, char *argv[]) {pthread_t tid;int test = 100;// 創建線程, 把 &test 傳給回調函數 thread_fun()pthread_create(&tid, NULL, thread_fun, (void *)&test); while(1);return 0; }?
?
?
?
?
?
運行結果如下:
?
?
4)回收線程資源
所需頭文件:
#include <pthread.h>
?
int pthread_join(pthread_t thread,?void **retval);
功能:
等待線程結束(此函數會阻塞),并回收線程資源,類似進程的 wait() 函數。如果線程已經結束,那么該函數會立即返回。
參數:
thread:被等待的線程號。
retval:用來存儲線程退出狀態的指針的地址。
返回值:
成功:0
失敗:非 0
?
示例代碼如下:
?
#include <stdio.h> #include <unistd.h> #include <pthread.h>void *thead(void *arg) {static int num = 123; //靜態變量printf("after 2 seceonds, thread will return\n");sleep(2);return # }int main(int argc, char *argv[]) {pthread_t tid;int ret = 0;void *value = NULL;// 創建線程ret = pthread_create(&tid, NULL, thead, NULL);if(ret != 0){ //創建失敗perror("pthread_create");}// 等待線程號為 tid 的線程,如果此線程結束就回收其資源// &value保存線程退出的返回值pthread_join(tid, &value); printf("value = %d\n", *( (int *)value ) );return 0; }?
?
?
?
?
?
運行結果如下:
?
?
創建一個線程后應回收其資源,但使用 pthread_join() 函數會使調用者阻塞,Linux 還提供了非阻塞函數 pthread_detach() 來回收線程的資源。
?
所需頭文件:
#include <pthread.h>
?
int pthread_detach(pthread_t thread);
功能:
使調用線程與當前進程分離,分離后不代表此線程不依賴與當前進程,線程分離的目的是將線程資源的回收工作交由系統自動來完成,也就是說當被分離的線程結束之后,系統會自動回收它的資源。所以,此函數不會阻塞。
參數:
thread:線程號。
返回值:
成功:0
失敗:非 0
?
注意,調用?pthread_detach() 后再調用?pthread_join() , pthread_join() 會立馬返回,調用失敗。
?
示例代碼如下:
?
#include <stdio.h> #include <unistd.h> #include <pthread.h>void *thead(void *arg) {int i;for(i=0; i<5; i++){printf("I am runing\n");sleep(1);}return NULL; }int main(int argc, char *argv[]) {int ret = 0;pthread_t tid;ret = pthread_create(&tid, NULL, thead, NULL);if(ret!=0){perror("pthread_create");}pthread_detach(tid); // 線程分離,不阻塞// 立馬返回,調用失敗int flag = pthread_join(tid, NULL);if(flag != 0){printf("join not working\n");}printf("after join\n");sleep(3);printf("I am leaving\n");return 0; }?
?
?
?
?
?
運行結果如下:
?
?
5)線程退出
在進程中我們可以調用 exit() 函數或 _exit() 函數來結束進程,在一個線程中我們可以通過 pthread_exit()?在不終止整個進程的情況下停止它的控制流。
?
所需頭文件:
#include <pthread.h>
?
void pthread_exit(void *retval);
功能:
退出調用線程。一個進程中的多個線程是共享該進程的數據段,因此,通常線程退出后所占用的資源并不會釋放。
參數:
retval:存儲線程退出狀態的指針。
返回值:
無
?
示例代碼如下:
?
#include <stdio.h> #include <unistd.h> #include <pthread.h>void *thread(void *arg) {static int num = 123; //靜態變量int i = 0;while(1){printf("I am runing\n");sleep(1);i++;if(i==3){pthread_exit( (void *)&num );// return #}}return NULL; }int main(int argc, char *argv[]) {int ret = 0;pthread_t tid;void *value = NULL;ret = pthread_create(&tid, NULL, thread, NULL); if(ret!=0){perror("pthread_create");}pthread_join(tid, &value);printf("value = %d\n", *(int *)value );return 0; }?
?
?
?
?
?
?
運行結果如下:
?
總結
以上是生活随笔為你收集整理的【Linux系统编程】线程的基本操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Protocol Buffer】Pro
- 下一篇: 【Linux系统编程】Linux文件操作