线程的控制(创建、等待、终止)、分离线程
一、線程控制
1、線程:線程是資源調度的基本單位,線程是進程內部的一個執行流,在進程的地址空間內運行。在Linux 下沒有真正意義上的線程,線程是用進程模擬的,又被稱為輕量級進程。
? ? ? ? 2、由于同?一進程的多個線程共享同?一地址空間。因此Text Segment、Data Segment都是共享的,除此之外,各線程還共享以下進程資源和環境:
1). ?文件描述符表;
2). 每種信號的處理?方式(SIG_IGN、SIG_DFL或者?自定義的信號處理函數);
3). 當前?工作?目錄;
4). ?用戶id和組id;
但有些資源是每個線程各有一份的:
1).線程id
2). 上下?文,包括各種寄存器的值、程序計數器和棧指針
3). 棧空間
4). errno變量
5). 信號屏蔽字
6). 調度優先級
3、線程創建:
? ? ??函數原型:int pthread_create(pthread_t?thread, const pthread_attr_t *attr, void?(start_routine) (void?), void *arg);?
創建成功:返回0 ;創建失敗:返回錯誤碼,可將錯誤碼通過strerror()轉換為字符串描述。?
參數1:線程id地址(只在用戶區有效)。?
參數2:線程屬性,一般設置為NULL。?
參數3:函數指針,指向線程函數。?
參數4:線程函數的參數。
?? ? ?
創建結果:?
?? ? ? ? ? ? ? ??
????? 如果需要只終?止某個線程?而不終?止整個進程,可以有三種?方法:
? ? ? ?1). 從線程函數return。這種?方法對主線程不適?用,從main函數return相當于調?用exit。
? ? ? ?2). ?一個線程可以調?用pthread_cancel終?止同?一進程中的另?一個線程,?用pthread_cancel終?止?一個線程分同步和異步兩種情況。
? ? ? ?3). 線程可以調?用pthread_exit終?止?自?己。
4、線程等待
? ? 返回值:成功返回0,失敗返回錯誤號
? ? 調?用該函數的線程將掛起等待,直到id為thread的線程終?止。thread線程以不同的?方法終?止,通過pthread_join得到的終?止狀態是不同的,總結如下:
? ? 1. 如果thread線程通過return返回,value_ptr所指向的單元?里存放的是thread線程函數的返回值。
? ? 2. 如果thread線程被別的線程調?用pthread_cancel異常終掉,value_ptr所指向的單元?里存放的是常數PTHREAD_CANCELED。
? ? 3. 如果thread線程是?自?己調?用pthread_exit終?止的,value_ptr所指向的單元存放的是傳給pthread_exit的參數。 如果對thread線程的終?止狀態不感興趣,可以 ? ? ?傳NULL給value_ptr參數
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
void* thread1(void* arg)
{
? ? printf("new thread1\n");
? ? return (void*)123;
}
void* thread2(void* arg)
{
? ? while(1)
? ? {
? ? ? ? printf("new thread2\n");
? ? ? ? sleep(1);
? ? ? ? pthread_exit((void*)456);
? ? }
? ??
}
void* thread3(void* arg)//被其他線程cancel
{
? ? while(1)
? ? {
? ? ? ? printf("new thread3\n");
? ? ? ? sleep(1);
? ? }
? ? return NULL;
}
int main()
{
? ? pthread_t tid1,tid2,tid3,tid4;
? ? void* val = NULL;
? ? pthread_create(&tid1,NULL,thread1,NULL);
? ? pthread_create(&tid2,NULL,thread2,NULL);
? ? pthread_create(&tid3,NULL,thread3,NULL);
? ? pthread_create(&tid4,NULL,thread4,NULL);
? ??
? ? pthread_join(tid1,&val);
? ? printf("thread1 is quit,thread1 id is %lu, exit code:%d\n",tid1,(int)val);
? ? pthread_join(tid2,&val);
? ? printf("thread2 is quit,thread2 id is %lu, exit code:%d\n",tid2,(int)val);
? ? pthread_cancel(tid3);
? ? pthread_join(tid3,&val);
? ? printf("thread3 is quit,thread3 id is %lu, exit code:%d\n",tid3,(int)val);
? ? return 0;
}?
運行結果:
注:
可見在Linux的pthread庫中常數PTHREAD_CANCELED的值是-1。可以在頭?文件pthread.h中找到它的定義。
一般情況下,線程終?止后,其終?止狀態?一直保留到其它線程調?用pthread_join獲取它的狀態為止。 但是線程也可以被置為detach 狀態,這樣的線程?一旦終止就?立刻回收它占?用的所有資源,?而不保留終?止狀態。不能對?一個已經處于detach狀態的線程調?用pthread_join,這樣的調?用將返回EINVAL。 對?一個尚未detach的線程調?用pthread_join或pthread_detach都可以把該線程置為detach狀態,也 就是說,不能對同?一線程調?用兩次pthread_join,或者如果已經對?一個線程調用 了pthread_detach就不能再調?用pthread_join了
二、分離線程
在任何?一個時間點上,線程是可結合的(joinable)或者是分離的(detached)。一個可結合的線程能夠被其他線程收回其資源和殺死。在被其他線程回收之前,
它的存儲器資源(例如棧)是不釋放的。相反,?一個分離的線程是不能被其他線程回收或殺死的,它的存儲器 資源在它終?止時由系統?自動釋放。
1、默認情況下,線程被創建成可結合的。為了避免存儲器泄漏,每個可結合線程都應該要么被顯?示地回收,即調?用pthread_join;要么通過調?用pthread_detach
函數被分離。如果?一個可結合線程結束運?行但沒有被join,則它的狀態類似于進程中的Zombie Process,即還有?一部分資源沒有被回收,所以創建線程者應該調用
pthread_join來等待線程運?行結束,并可得到線程的退出代碼,回收其資源。
2、?由于調?用pthread_join后,如果該線程沒有運?行結束,調?用者會被阻塞,在有些情況下我們并不希望如此。例如,在Web服務器中當主線程為每個新來的連接
請求創建?一個?子線程進?行處理的時候,主線程并不希望因為調?用pthread_join?而阻塞(因為還要繼續處理之后到來的連接請求),這時可以在?子線程中加入
代碼?pthread_detach(pthread_self());
或者?父線程調?用pthread_detach(thread_id)(?非阻塞,可?立即返回)
這將該?子線程的狀態設置為分離的(detached),如此一來,該線程運?行結束后會?自動釋放所有資源。
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
void* thread(void *_arg)
{
? ? //pthread_detach(pthread_self());//線程自已設置自已的可分離屬性
printf("new thread is run...\n");
? ? return (void*)1;
}
int main()
{
? ? pthread_t tid;
? ? int ret = pthread_create(&tid,NULL,thread,NULL);
? ? if(ret != 0)
? ? {
? ? ? ? printf("thread create failed,error code:%s\n",strerror(ret));
return ret;
? ? }
? ? sleep(1);
? ? pthread_detach(tid);//將子線程屬性設置為分離(非阻塞,可立即返回)
? ? void* val = NULL;
? ? if((pthread_join(tid, &val) != 0))
? ? {
? ? ? ? printf("thread wait failed\n");
ret = 1;
}
? ? else
? ? {
? ? ? ? printf("thread id : %u ,exit code : %d\n",tid, (int)val);
ret = 0;?
? ? }
? ? return ret;
}
運行結果:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
總結
以上是生活随笔為你收集整理的线程的控制(创建、等待、终止)、分离线程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【报告分享】 百度2021国潮骄傲搜索大
- 下一篇: 教你炒股票21:缠中说禅买卖点分析的完备