深入Phtread(一):線程的一生

深入Phtread(一):線程的一生

 
    我們每個人都並行地活在這個世界上 ,每一天每個人都幹着不同的事情。每個人的人生都是不同的,從出生 -> 活着 -> 死去, 箇中滋味,只能自己體味了。我們的線程兄弟也一樣,只不過它的環境沒有人類社會這麼複雜,它的一生,被操作系統控制,被我們程序員控制着!呵呵,想想都覺得這兄弟可憐啊!不過這哥們可不許小瞧了,功能大了去了!具體線程的定義和好處參考其它關於線程的資料。該篇主要講線程兄弟的大體的一生(從被創建到銷燬)。進入正題:
    線程的一生始終處於下面四種狀態之一: 
State Meaning
Ready 就緒狀態,等待處理器的調度。可能是剛新創建的,或阻塞狀態,等待的資源得到滿足剛解除阻塞狀態,或處於運行狀態被別的線程搶佔了處理器。
Running 運行狀態,線程正在處理器上運行。多處理器可能會不止一個線程正在運行。
Blocked 阻塞狀態,線程等待某些資源,不能運行。如:等待一個條件變量,鎖定互斥量,或者等待I/O操作的完成。
Terminated 終止狀態,線程從它的開始函數(創建時指定的)終止。調用pthread_exit或者被其它線程取消(cancelled)。此時,線程並沒有被分離(detached),也沒有被連接(joined)。一旦線程被joined或detached, 將會被系統回收。

    線程的狀態圖:
 

1. 創建和使用線程常見的pthread函數 

pthread_t thread;
int pthread_equal(pthread_t t1, pthread_t t2);
int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void* (*start)(void*), void* arg);
pthread_t pthread_self();
int sched_yield();
int pthread_exit(void* value_ptr);
int pthread_detach(pthread_t thread);
int pthread_join(pthread_t thread, void** value_ptr);

2. 創建線程:

    有一個比較特殊的線程, 就是主線程或者稱爲初始線程,它是當一個進程被創建時創建的。而其他線程則是在初始線程中調用pthread_create創建的。創建的新線程初始爲Ready狀態,等待處理器調度。

3. 執行線程:

    線程被創建後,就會執行phtread_create的start參數指定的函數,我們可以通過pthread_create的arg參數向線程開始函數傳遞一個參數,若不想傳就直接賦值NULL。
上面提到了一個特殊的線程:初始線程,它的開始函數就是我們學習C/C++見到的第一個函數main,只不過這個開始函數不是由我們來調用的,而是由操作系統Shell。操作系統先初始化進程,然後運行主線程的開始函數main。注意:初始線程和我們自己創建的線程有稍許不同:-開始函數參數不同,main的參數是int arg, char* argv,而我們自己的線程參數是void* arg。-自己創建的線程開始函數返回了,其它線程可以繼續執行。而初始線程開始函數main返回後進程會終止,導致其它正在運行的線程也就被強行終止,若不想在main退出後關閉進程,可以在main最後調用pthread_exit,不過此時該進程就成了殭屍進程(defunct),直到所有線程執行完畢。- 還有一個很重要的區別,多數系統上,初始線程使用的是進程的棧,而自己創建的線程則使用自己的棧,往往自建線程的棧沒有初始線程的棧空間大,要注意線程棧溢出哦!(phread提供了修改線程棧大小的函數,後面再說^_^)

4. 運行和阻塞 

    線程兄弟和我們一樣,不能一直都醒着工作,它也要休息。線程一生大多處於三種狀態:ready, running, 和blocked(和我一樣,吃飯,工作,睡覺^_^)。 線程被創建時出於就緒狀態,就緒狀態等待處理器,處理器有空閒了,線程就轉到運行狀態瘋狂工作,突然發現自己需要的其它資源(互斥量,條件變量)在別的線程手裏,或者別的線程優先級比自己大一下從它手裏搶走了處理器,或處理器煩了它了(時間片已經用完),或自己不好意思不幹事還佔用處理器了(等待I/O操作完成),就轉換成阻塞狀態,停止運行,可以休息下了。 休息可不是給它放長假,任務還沒完成了...繼續,當等待的資源得到滿足,再次投入工作,進入運行狀態。周而復始,直到任務完成。

5. 終止線程:

    線程一般都是在開始函數執行完時終止的。線程開始函數中調用pthread_exit或者其它線程調用pthread_cancel都可以終止線程。終止後線程處於terminated狀態(注意:不是destroyed),然後等待系統回收。
 
    若創建線程時指定線程是detached的,直接在線程開始函數執行完後就會被回收。
若是joinable,那就需要初始線程或其他線程調用pthread_join來等待要終止的線程了, 同時還可以通過pthread_joind的第二個參數獲得線程的返回值。pthread_join後,線程就被detached,然後被系統回收。

6. 回收線程

    線程創建時,detachsate屬性是PTHREAD_CREATE_DETACHED,則在開始函數返回後被回收。
或其他線程使用了pthread_join 或自己調用了pthread_detach,線程出於terminated狀態後,立馬就會被系統回收:釋放系統資源和進程資源,包含線程返回值佔用的內存,線程堆棧,寄存器狀態等等。
 
    今天就到此,以後深挖!^_^
 
發佈了8 篇原創文章 · 獲贊 5 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章