Linux關於多執行緒技術
執行緒的概念
在一個程式裡的多個執行路線就叫做執行緒(thread)。更準確的定義是:執行緒是“一個程序內部的控制序列” 一切程序至少都有一個執行執行緒
執行緒的優點
建立一個新執行緒的代價要比建立一個新程序小得多 與程序之間的切換相比,執行緒之間的切換需要作業系統做的工作至少在理論上要少很多 執行緒佔用的資源要比程序少很多
執行緒的函式使用
與執行緒有關的函式構成了一個完整的系列,絕大多數函式的名字都是以“pthread_”打頭的 要使用這些函式庫,要通過引入標頭檔案<pthread.h> 連結這些執行緒函式庫時要使用編譯器命令的“-lpthread”選項
建立執行緒函式
int pthread_create(pthread_t *thread, pthread_attr_t *attr, void*(*start_routine)(void*), void *arg);
函式引數的理解:
thread:新執行緒建立成功後,儲存新執行緒的識別符號 attr:設定執行緒的屬性,一般不需要什麼特殊的屬性,直接傳 NULL即可 start_routine: 是個函式地址,執行緒啟動後要執行的函式 arg:傳給執行緒啟動函式的引數“void* (*start_routine)(void*) ”表示需要我們傳遞的一個函式地址,該函式以一個指向void的指標為引數,返回的也是一個指向void的指標。 呼叫成功時返回值是“0”,如果失敗則返回一個錯誤。
接下來就來一段程式碼:(下面程式碼實現兩個執行緒,task_set_name函式是給執行緒設定名字)
#include<stdio.h> #include<unistd.h> #include<pthread.h> #include<stdlib.h> #include<string.h> #include<sys/syscall.h> #include<sys/prctl.h> int task_set_name(const char *name) { char thread_name[128]={0}; if(!name) return -1; snprintf(thread_name,sizeof(thread_name),"%s(%ld)",name,syscall(SYS_gettid)); prctl(PR_SET_NAME,thread_name,0,0,0); return 0; } void *routine1 (void *arg[]) { char *pbuf=(char *)arg; int i; task_set_name("aa"); printf("%s,pid = 0x%08x\n",pbuf,(int)pthread_self()); for(;i<5;i++) { putchar('A'); fflush(stdout); sleep(1); } pthread_exit("pthread1"); return 0; } void *routine2(void *arg[]) { char *pbuf=(char *)arg; int i; printf("%s,pid = 0x%08x\n",pbuf,(int)pthread_self()); for(;i<5;i++) { putchar('B'); fflush(stdout); sleep(1); } pthread_exit("pthread2"); return 0; } int main(int argc,char *argv[]) { int i; char *thread_buf = "this is first!\n"; pthread_t tid,tid1; //1.建立執行緒1 int ret = pthread_create(&tid,NULL,routine1,thread_buf); if(ret < 0) { fprintf(stderr,"thread create failed:%s\n",strerror(ret)); } ret = pthread_create(&tid1,NULL,routine2,thread_buf); if(ret != 0) { fprintf(stderr,"thread create faile:%s\n",strerror(ret)); } sleep(2); for(i = 0;i<5;i++) { putchar('c'); fflush(stdout); } //2.等待執行緒回收 char *pre; pthread_join(tid,(void**)&pre); printf("======%s\n",pre); pthread_join(tid1,(void**)&pre); printf("=====%s\n",pre); return 0; }
程式碼結果
首先我看看到兩個執行緒被建立,接下來就是兩個執行緒裡面實現rountine1和rountine2都是個函式地址,執行緒啟動後要執行的函式
分別執行輸出A和B,接下來就是主函式輸出c,最後就是執行緒回收