在寫這篇文章之前,***已經寫過了幾篇關於改函式程序主題的文章,想要了解的朋友可以去翻一下之前的文章
執行緒(thread)----輕量級的程序、cpu排程的最小單位,相比較於程序,程序是分配資源的最小單位。
之前講到的是多程序程式設計,這一部份要說的是如安在乙個程序中實現多執行緒程式設計(當然將程序部份的內容放到一起,就可以實現多程序多執行緒程式設計)。posix(可移植性操縱系統介面)劃定了可移植性的執行緒庫pthread庫,這裡面的函式需要在編譯時加上-lpthread(-pthread)引數,pthread庫中的型別以及函式是不透明的(把握如何使用,不必關懷如何實現)。
乙個程序中至少有乙個執行緒,從main()開始執行的執行緒稱為 主線程(初始執行緒)。執行緒id型別pthread_t,可以使用pthread_self()返回,需要注意的是,執行緒id只是在乙個程序內有效(程序id在整個系統中有效);使用pthread_equal()比較兩個執行緒的id是否相稱。
pthread_t pthread_self(void);
int pthread_equal(pthread_t tid1, pthread_t tid2);
執行緒創立的創立使用pthread_create()函式:
int pthread_create(pthread_t *tidp, const pthread_attr_t *attr, void *(*start_rtn)(void*), void *arg);
函式的第乙個引數tidp,是乙個出參,用來帶回被創立執行緒的tid;第二個引數attr設定的執行緒屬性(前面說明),默許屬性傳null即可;第三個引數start_rtn是乙個函式指標,是被創立執行緒的進口函式(新執行緒從該函式開始執行至該函式結束);第四個引數arg是start_rtn函式的引數;該函式呼叫成功返回0,否則返回出錯編碼(不使用errno全域性變數)。幾點需要注意:
1.受os排程影響,被創立的執行緒處於就緒狀態,故創立執行緒的執行緒往往是先被呼叫。
2.統一程序中的多個執行緒共享記憶體資源,故多個執行緒對程序中的所有變數都是共享的(但要注意該變數的生存期和作用域)。
3.只要程序(主線程)退出,其餘未結束的執行緒都隨之結束了(程序結束資源也就沒了)
4.統一程序中的多個執行緒共享檔案描述符,並非複製乙份。
5.統一程序中的多個執行緒共享程序的訊號遮蔽字,但新執行緒的未決訊號集講被清空。
程序退出的方式:從start_rtn返回;自身呼叫pthread_exit()函式;被統一個程序中的其他執行緒取消。先來看pthread_exit()函式和與之配套的pthread_join()函式:
void pthread_exit(void *rval_ptr);
int pthread_join(pthread_t thread, void **rval_ptr);
pthread_exit()函式相似於程序中的exit()函式,執行緒直接終止,並將rval_ptr引數作為執行緒的返回值。pthread_join()的功能相似程序的waitpid(pid)函式,阻塞等待指定的執行緒退出並接受返回值,引數是void **型別,是乙個出參引數。
執行緒中也有相似程序atexit()註冊清理操縱的函式,pthread_cleanup_push() pthread_cleanup_pop()註冊執行緒的清理函式。
每日一道理
風,那麼輕柔,帶動著小樹、小草一起翩翩起舞,當一陣清風飄來,如同母親的手輕輕撫摸自己的臉龐,我喜歡那種感覺,帶有絲絲涼意,讓人心曠神怡。享受生活,不一定要有山珍海味、菱羅綢緞為伴,大自然便是上帝所賜予人類最為珍貴的。
void pthread_cleanup_push(void (*rtn)(void *), void *arg);
void pthread_cleanup_pop(int execute);
註冊的函式有兩個引數,乙個是函式指標,乙個是該函式接收的引數。第二個函式在執行後會設定之前註冊的函式的執行狀態,如果execute為0則不執行否則執行,需要注意的是,這兩個函式必須是在乙個函式內成對出現(具體實現應該是帶括號的巨集定義),但可以斟酌放到pthread_exit()後。
再來說下pthread_cancel()函式,它和pthread_exit()都能使乙個執行緒退出,不同是後者是使執行緒本身退出,而前者是使統一程序中的其他執行緒退出。
int pthread_cancel(pthread_t tid);
該函式的道理是:向tid執行緒傳送sigcancel訊號(這個訊號在kill -l中查詢不到)。只是傳送乙個訊號作為請求,但指定的執行緒是否退出何時退出pthread_cancel()其實不關懷,這就涉及到乙個問題,乙個執行緒在接收到sigcancel訊號時何時退出,有個取消點的概念。大部份的pthread函式以及阻塞的系統呼叫都是取消點,增加設定取消點的函式是pthread_testcancel():
void pthread_testcancel(void);
int pthread_setcancelstate(int state, int *oldstate);
int pthread_setcanceltype(int type, int *oldtype);
分離用來設定取消狀態和取消型別。取消狀態包括pthread_cancel_enbale可以被取消 pthread_cancel_disable不允許被取消;取消型別包括pthread_cancel_deferred直到取消點才終止 pthread_cancel_asynchronous當即終止(這個在很多平台下是不好用的)
再介紹一下其他的執行緒屬性,執行緒屬性的型別是pthread_attr_t型別,型別的初始化和銷毀分離是pthread_attr_init() pthread_attr_destroy()兩個函式:
int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);
執行緒的屬性包括:分離屬性 繫結屬性 執行緒棧屬性等等,這裡我們只說下分離屬性(其餘的用不到)。如果乙個執行緒被分離了,那麼創立它的執行緒即使呼叫了pthread_join()也不能等待並接受該執行緒的返回值。設定分離屬性有兩種方法,第一種是直接呼叫pthread_detach()函式,第二其中是將執行緒屬性傳入到pthread_create()函式中。
int pthread_detach(pthread_t tid);
int pthread_attr_getdetachstate(const pthread_attr_t * attr, int *detachstate);
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
pthread_detach()函式使tid執行緒分離,前面兩個函式操縱的是執行緒屬性的結構,detachstate的值可所以pthread_create_joinable不分離(默許的) pthread_create_detached分離。這兩種方法的區別是,第一種用於執行緒已被創立後分離,另一種用於創立前設定。
文章結束給大家分享下程式設計師的一些笑話語錄: 這年頭的網際網路真是娛樂了中國,網民們從各種各樣的「門」裡鑽來鑽去,又有好多「哥」好多「帝」,值得大家品味不已……網路經典語錄,關於it與網際網路,經典與您分享!
--------------------------------- 原創文章 by
函式和程序
---------------------------------
APUE學習 程序控制
程序識別符號在系統中是唯一的。unix採用延遲技術來分配pid。因為,如果乙個程序終止了,馬上把他的pid分配給新的程序,而且這個新程序與舊程序要做一樣的事。那麼別人就不知道這是新程序還是舊程序在做了。類似於tcp4次揮手的最後一步。還有一些特殊的程序,例如pid為0的程序,這個可以看成是乙個核心的...
APUE 程序環境
mian函式 c程式總是從main函式開始執行。main函式的原型是 int main int argc,char argv 其中,argc是命令列引數的數目,argv是指向引數的各個指標所構成的陣列。當核心執行c程式時,在呼叫main之前先呼叫乙個特殊的啟動例程。可執行程式檔案將此啟動例程指定為程...
APUE 程序環境
本文使用golang的syscall,os,golang.org x sys unix包 main是程式的入口,golang中也亦是如此 啟動乙個程式時啟動例程負責從核心獲取命令列引數和環境變數,維護到程式的記憶體布局中 後文描述 import os func exit code int 使程式主動...