Linux下執行緒的概念和使用
阿新 • • 發佈:2018-12-26
一. 概念
首先Linux並不存在真正的執行緒,Linux的執行緒是使用程序模擬的。當我們需要在一個程序中同時執行多個執行流時,我們並不可以開闢多個程序執行我們的操作(32位機器裡每個程序認為它 獨享 4G的記憶體資源),此時便引入了執行緒,例如當我們既需要下載內容,又需要瀏覽網頁時,此時多執行緒便起了作用。執行緒是承擔排程的基本單位,一個程序可擁有多個執行緒,它的執行力度比程序更加細緻,執行緒資源共享。
二. 特點
由於同一程序的多個執行緒共享同一地址空間,所以程式碼段,資料段是共享的,如果定義一個函式(儲存在程式碼段),各執行緒都可以進行呼叫,如果定義個全域性變數(儲存在資料段),在各執行緒中都可以訪問到,除此之外,各執行緒還共享以下程序資源和環境:
1.檔案描述符表
2.每種訊號的處理方式(SIG_IGN,SIG_DFL,使用者自定義)
3.當前工作目錄
4.使用者id和組id
但有些資源是執行緒獨享
1.執行緒id
2.上下文,包括各種暫存器的值,程式計數器和棧指標
3.棧空間
4.errno變數
5.訊號遮蔽字
6.排程優先順序
三. 執行緒的簡單實用
1.建立執行緒
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
返回值:成功返回0,失敗返回錯誤號。在一個執行緒中調pthread_create()建立新的執行緒後,當前執行緒從pthread_create()返回繼續往下執行,新的執行緒所執行的程式碼由我們傳給pthread_create的函式指標start_routine決定。
thread引數傳入執行緒的id,void
2.執行緒終止
void pthread_exit(void *retval)函式用於程序終止,傳入一個id,呼叫exit()的話,主程序會終止。終止執行緒由三種方法:
1).從執行緒函式return。這種方法法對主執行緒不適用,從main函式return相當於呼叫exit。
2).一個執行緒可以呼叫pthread_cancel終止同一程序中的另一個執行緒。
3).執行緒可以調pthread_exit終自己。
retval是void *型別,其它執行緒可以調pthread_join獲得這個指標。
3.執行緒等待
int pthread_join(pthread_t thread,void **retval);成功返回0,失敗返回錯誤號。 執行緒的等待是以阻塞式等待,執行緒不等待會產生記憶體洩露(類似程序的殭屍程序)
4.程序取消
在合理範圍內,執行緒可以自我或者被別人取消。取消後返回PTHREAD_CANCELED(它被定義為(void *)-1),取消呼叫函式pthread_cancel(id);
5.執行緒分離
在任何一個時間點上執行緒是可結合的(joinable)或者是分離的(detached)。一個可結合的執行緒能夠被其他執行緒收回其資源和殺死。在被其他執行緒回收之前,它的儲存器資源(例如棧)是不釋放的。相反一個分離的執行緒是不能被其他執行緒回收或殺死的,它的儲存器資源在它終時時由系統自動釋放。
預設情況一個執行緒是可結合的,每一個可結合的執行緒都應該被顯性的回收,既呼叫pthread_join()函式,分離呼叫函式pthread_detach。分離的這個函式是非阻塞的,可以立即返回。但為什麼要分離呢?因為主程序在處理執行緒時,要處理不止一個,而每一個都需要被等待,然而join是阻塞式的,這樣的話就只能處理一個執行緒,所以要加入分離,這樣就可以處理多個執行緒。呼叫pthread_detach()後,這些子程序的狀態會被設定為分離的,該執行緒執行結束會自動釋放所有資源。
下面為測試程式碼:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void* thread1()
{
pthread_detach(pthread_self());//分離後仍可被等待
printf("pid is: %d, tid is: %d\n", getpid(),pthread_self());
return (void*)1;
}
int main()
{
pthread_t tid;
void *ret;
int err = pthread_create(&tid, NULL, thread1, NULL);
if (err != 0)
{
perror("pthread_create\n");
return err;
}
//如果直接執行等待程式碼,一般會等待成功,返回1
//如果在等待之前加入取消。等待錯誤,返回-1
// pthread_cancel(tid);
//執行緒可以自我取消也可以被取消,執行緒終止
//呼叫pthread_exit(tid);和取消同樣用法。
int tmp = pthread_join(tid, &ret);
if (tmp == 0)
{
printf("wait success\n");
}
else
{
printf("wait failed\n");
}
printf(" pid is: %d, tid is: %d\n", getpid(),pthread_self());
sleep(1);
return 0;
}