linux執行緒控制原語2

2021-07-25 14:49:50 字數 3981 閱讀 1896

將單個執行緒退出

void pthread_exit(void *retval); 引數:retval表示執行緒退出狀態,通常傳null

思考:使用exit將指定執行緒退出,可以嗎? 【pthrd_exit.c】

#include #include #include #include void *tfn(void *arg)

int main(int argc, char *argv)

sleep(n);

printf("i am main, i'm a thread!\n"

"main_thread_id = %lu\n", pthread_self());

return 0;

}

結論:執行緒中,禁止使用exit函式,會導致程序內所有執行緒全部退出。

在不新增sleep控制輸出順序的情況下。pthread_create在迴圈中,幾乎瞬間建立5個執行緒,但只有第1個執行緒有機會輸出(或者第2個也有,也可能沒有,取決於核心排程)如果第3個執行緒執行了exit,將整個程序退出了,所以全部執行緒退出了。

所以,多執行緒環境中,應盡量少用,或者不使用exit函式,取而代之使用pthread_exit函式,將單個執行緒退出。任何執行緒裡exit導致程序退出,其他執行緒未工作結束,主控執行緒退出時不能return或exit。

【練習】:編寫多執行緒程式,總結exit、return、pthread_exit各自退出效果。

return:返回到呼叫者那裡去。

pthread_exit():將呼叫該函式的執行緒

exit: 將程序退出。

阻塞等待執行緒退出,獲取執行緒退出狀態 其作用,對應程序中 waitpid() 函式。

int pthread_join(pthread_t thread, void **retval); 成功:0;失敗:錯誤號

引數:thread:執行緒id (【注意】:不是指標);retval:儲存執行緒結束狀態。

對比記憶:

程序中:main返回值、exit引數-->int;等待子程序結束 wait 函式引數-->int *

執行緒中:執行緒主函式返回值、pthread_exit-->void *;等待執行緒結束 pthread_join 函式引數-->void **

【練習】:引數 retval 非空用法。 【pthrd_exit_join.c】

#include #include #include #include typedef struct  exit_t;

void *tfn(void *arg)

int main(void)

呼叫該函式的執行緒將掛起等待,直到id為thread的執行緒終止。thread執行緒以不同的方法終止,通過pthread_join得到的終止狀態是不同的,總結如下:

1. 如果thread執行緒通過return返回,retval所指向的單元裡存放的是thread執行緒函式的返回值。

2. 如果thread執行緒被別的執行緒呼叫pthread_cancel異常終止掉,retval所指向的單元裡存放的是常數pthread_canceled。

3. 如果thread執行緒是自己呼叫pthread_exit終止的,retval所指向的單元存放的是傳給pthread_exit的引數。

4. 如果對thread執行緒的終止狀態不感興趣,可以傳null給retval引數。

【練習】:使用pthread_join函式將迴圈建立的多個子執行緒**。 【pthrd_loop_join.c】

#include #include #include #include int var = 100;

void *tfn(void *arg)

else if (i == 3) else

return null;

}int main(void)

printf("i'm main pthread tid = %lu\t var = %d\n", pthread_self(), var);

sleep(i);

return 0;

}

實現執行緒分離

int pthread_detach(pthread_t thread); 成功:0;失敗:錯誤號

執行緒分離狀態:指定該狀態,執行緒主動與主控執行緒斷開關係。執行緒結束後,其退出狀態不由其他執行緒獲取,而直接自己自動釋放。網路、多執行緒伺服器常用。

程序若有該機制,將不會產生殭屍程序。殭屍程序的產生主要由於程序死後,大部分資源被釋放,一點殘留資源仍存於系統中,導致核心認為該程序仍存在。

也可使用 pthread_create函式參2(執行緒屬性)來設定執行緒分離。

【練習】:使用pthread_detach函式實現執行緒分離 【pthrd_detach.c】

#include #include #include #include #include void *tfn(void *arg)

//return (void *)1;

pthread_exit((void *)1);

}int main(void)

return 0;

}

一般情況下,執行緒終止後,其終止狀態一直保留到其它執行緒呼叫pthread_join獲取它的狀態為止。但是執行緒也可以被置為detach狀態,這樣的執行緒一旦終止就立刻**它占用的所有資源,而不保留終止狀態。不能對乙個已經處於detach狀態的執行緒呼叫pthread_join,這樣的呼叫將返回einval錯誤。也就是說,如果已經對乙個執行緒呼叫了pthread_detach就不能再呼叫pthread_join了。

殺死(取消)執行緒 其作用,對應程序中 kill() 函式。

int pthread_cancel(pthread_t thread); 成功:0;失敗:錯誤號

【注意】:執行緒的取消並不是實時的,而有一定的延時。需要等待執行緒到達某個取消點(檢查點)。

類似於玩遊戲存檔,必須到達指定的場所(存檔點,如:客棧、倉庫、城裡等)才能儲存進度。殺死執行緒也不是立刻就能完成,必須要到達取消點。

取消點:是執行緒檢查是否被取消,並按請求進行動作的乙個位置。通常是一些系統呼叫creat,open,pause,close,read,write..... 執行命令man 7 pthreads可以檢視具備這些取消點的系統呼叫列表。也可參閱 apue.12.7 取消選項小節。

可粗略認為乙個系統呼叫(進入核心)即為乙個取消點。如執行緒中沒有取消點,可以通過呼叫pthreestcancel函式自行設定乙個取消點。

被取消的執行緒, 退出值定義在linux的pthread庫中。常數pthread_canceled的值是-1。可在標頭檔案pthread.h中找到它的定義:#define pthread_canceled ((void *) -1)。因此當我們對乙個已經被取消的執行緒使用pthread_join**時,得到的返回值為-1。

【練習】:終止執行緒的三種方法。注意「取消點」的概念。 【pthrd_endof3.c】  

#include #include #include #include void *tfn1(void *arg)

void *tfn2(void *arg)

void *tfn3(void *arg)

return (void *)666;

}int main(void)

總結:終止某個執行緒而不終止整個程序,有三種方法:

1. 從執行緒主函式return。這種方法對主控執行緒不適用,從main函式return相當於呼叫exit。

2. 乙個執行緒可以呼叫pthread_cancel終止同一程序中的另乙個執行緒。

3. 執行緒可以呼叫pthread_exit終止自己。

比較兩個執行緒id是否相等。

int pthread_equal(pthread_t t1, pthread_t t2);

有可能linux在未來執行緒id pthread_t 型別被修改為結構體實現。

程序 執行緒控制原語對比

程序 執行緒 fork pthread create exit int pthread exit wait int pthread join void kill pthread cancel 殺死執行緒,但必須到達取消點 getpid pthread self 命名空間 注 執行緒處於分離狀態,不可...

程序控制原語

unix 下的程序控制原語用於控制程序的建立 執行 終止等。其基本原語如下 用 fork 建立新程序,用 exec 執行新的程式,exit 函式和兩個 wait 函式處理終止和等待終止。下面分別講解一下 除了交換程序 init 程序和精靈程序 daemon 外,乙個現存程序呼叫 fork 函式是un...

linux執行緒控制

1.執行緒屬性 a 分離狀態 不需要了解執行緒返回終止狀態時設定 b 棧末尾警戒緩衝區 避免棧溢位的擴充套件記憶體大小,一般系統設定為頁的整數倍 c 棧的最小位址 i.當有許多執行緒時,減少棧大小 ii.當執行緒中有許多自動變數時,則增大棧大小 d 棧的最小長度 2.互斥量屬性 a 程序共享屬性 i...