Linux環境下程式設計(二) 執行緒基礎概念

2021-07-04 02:51:35 字數 3162 閱讀 7556

基礎概念

執行緒,有時被稱為輕量級程序(lightweight process,lwp),是程式執行流的最小單元。乙個標準的執行緒由執行緒id,當前指令指標(pc),暫存器集合和堆疊組成。

經常被問到的乙個問題是:執行緒和程序有什麼區別?為什麼要有執行緒這樣乙個東西?

執行緒是執行在程序上下文中的邏輯流,最開始的時候乙個程序對應乙個主線程。後來覺得既然好多資源是可以共享的,為什麼每次都要建立乙個新的程序?不斷地去切換程序的上下文造成了很多不必要的開銷。既然有的資源可以共享,那麼我們乾脆弄乙個輕量級的程序,這樣切換起來豈不是快得多?而且現在作業系統都是多核的,既然它有幾個腦子,那麼每個腦子繫結乙個執行緒,然後共同支配乙個身體,豈不是更快?(當然了這段話說的並不是太嚴謹,僅供理解)。

同一程序裡的執行緒,哪些資源是獨佔的,哪些資源是共享的?

獨有的:執行緒id、棧、棧指標、程式計數器、條件碼、通用目的暫存器。

下面講講具體的應用

posix執行緒是在c語言執行緒的標準介面。

乙個執行緒對應乙個執行緒id,它的型別是pthread_t,是乙個自然數,但是這個並不是int型,而是無符號長整型,列印的時候要用%lu。

執行緒獲取自身id的函式為:

#include pthread_t pthread_self(void);
執行緒的建立介面為:

#includetypedef void* (func)(void *);

int pthread_create(pthread_t* tid, pthread_attr_t* attr,func* f, void* arg)

pthread_create和程序的建立函式有些區別,它的返回值不是執行緒的id,而是返回0或者非0,0代表建立成功,非0代表建立失敗。

我們來看它的引數列表,第乙個引數tid,就是我們傳入的tid的位址,然後函式結束後,tid的值將會變成子程序的id。

第二個引數為執行緒建立的一些選項,預設是null。

第三個引數為乙個函式位址,func*為函式指標,執行緒就從這個位址開始執行。

第四個引數為傳遞給執行緒函式的引數,如果執行緒函式需要多個引數的話,那麼就把它作為結構體的形式傳入。

下面來看乙個具體例項:

#include#include#includetypedef void* (func)(void *);

void error_msg(int ret, char *msg)

void pthread_create(pthread_t* tid, pthread_attr_t* attr,func* f, void* arg)

}void* pthread_instance(void* args)

int main(void)

執行結果:

結果分析:

1、在用gcc編譯的時候,需要在後面加上動態鏈結庫

2、為什麼程式的倒數第三行需要加上sleep(1)?假如我把sleep(1)給注釋掉,會出現什麼情況?

注釋掉sleep(1)

執行結果:

我們發現,子執行緒(也可以叫對等執行緒)的printf語句並沒有被列印出來,這個到底是為什麼?

其實,在主線程中的exit語句不僅將主線程退出了,更重要的是它終止了程序,當程序沒有了,依賴它的子執行緒自然就不能夠正常執行,所以那句話沒有打出來。

如果我們加上了sleep(1)主線程休眠了1下,這個時候子執行緒先正常執行完畢,然後接著主線程也執行完畢,所以會列印兩個printf出來。

對等執行緒(就是主線程建立的執行緒)的**

很顯然,上面的sleep(1)造成了乙個問題,就是很多時候我們根本不知道主線程和對等執行緒的執行時間,只是通過sleep人為地去判斷時間,是不是有點不妥當?

這個時候我們有兩個方法來處理:

1、採用pthread_join函式,

#includeint pthread_join(pthread_t tid, void **thread_return);
成功則返回0,不成功則返回非0.

執行緒通過呼叫phread_join 來等待其它執行緒終止,pthread_join函式會阻塞,直到tid終止,將執行緒呼叫返回的(void*)指標賦值為thread_return指向的位置,然後**已終止執行緒占用的所有儲存器資源。

具體實驗如下:

et, char *msg)

void pthread_create(pthread_t* tid, pthread_attr_t* attr,func* f, void* arg)

}void pthread_join(pthread_t tid, void **thread_return)

}void* pthread_instance(void* args)

int main(void)

執行結果:

結果分析:

1、是不是和上面結果一樣?主線程**了pthread_join等待的對等執行緒資源後才退出。

2、大家注意到了我下面注釋掉的兩行**沒有?

分離乙個程序的函式為下,成功返回0,出錯返回非0。

#includeint pthread_detach(pthread_t tid);
那麼,有什麼辦法能夠讓主線程在終止的時候先等待對等執行緒終止呢?有的,這個就是pthread_exit幹的事情了。

pthread_exit函式,若成功則返回0,出錯返回非0。

#includephread_exit(void *thread_return);
大家可以試試,是不是把pthread_join注釋掉,然後採用pthread_detach和pthread_exit之後結果一樣。

Linux多執行緒程式設計(二) 執行緒屬性

pthread介面允許我們通過設定每個物件關聯的不同屬性來細調執行緒的行為。include int pthread attr init pthread attr t attr int pthread attr destroy pthread attr t attr 兩個函式的返回值 若成功,返回0 ...

linux 之執行緒基礎 二 執行緒相關API

2.1.1 程序id的資料型別 2.1.2 執行緒id的資料型別 注意 2.2.1 函式原型 include intpthread create pthread t thread,const pthread attr t attr,void start routine void void arg 2...

linux 之執行緒基礎 二 執行緒相關API

2.1.1 程序id的資料型別 2.1.2 執行緒id的資料型別 注意 2.2.1 函式原型 include intpthread create pthread t thread,const pthread attr t attr,void start routine void void arg 2...