Linux--線程式控制制__Linux

來源:互聯網
上載者:User
一、線程的概念

線程,有時被稱為輕量級進程(Lightweight Process,LWP),是程式執行流的最小單元。線程是進程中的一個實體,是被系統獨立調度和指派的基本單位,線程自己不擁有系統資源,只擁有一點兒在運行中必不可少的資源,但它可與同屬一個進程的其它線程共用進程所擁有的全部資源。
在單個程式中同時運行多個線程完成不同的工作,稱為多線程。 二、Linux中線程的特點

1、Linux中沒有正真意義上的線程,是通過進程來類比的,也就是說Linux的線程的本質就是進程。
2、管理線程的問題。每個進程擁有一個管理線程,進程內部線程的建立、銷毀、同步都經過管理線程處理。通過管理線程,實現了下面對於多線程的要求:

系統必須有能力殺死整個進程。
線程棧的回收必須在對應線程結束後執行,所以線程不能自己處理。
將要終止的線程必須能夠被等待,從而不至於成為殭屍。
線程資料區的回收需要對所有線程迭代執行,這個任務要管理線程完成。
如果主線程需要調用pthread_exit(),而進程並沒有終止,主線程就睡眠,直到其他線程終止後,由管理線程喚醒主線程。
3、為了維護線程資料和記憶體,LinuxThreads使用進程地址空間的高位部分,即低於進程棧空間的部分。
4、基於訊號機制實現線程同步。
5、LinuxThreads把每個線程實現為一個進程,擁有一個唯一的進程ID。
6、當進程收到終止訊號,由管理線程負責用此訊號殺死其他線程。
7、如果某個非同步訊號被發送,管理線程把訊號傳遞給某個線程,如果該線程當前阻塞了該訊號,則訊號就是pending狀態。
8、核心調度器實現對線程的調度。 三、線程與進程的區別

1、進程強調的是資源獨佔;而線程強調的是資源共用;
2、進程與進程之間是沒有任何交際的;同一個進程下的線程與線程之間共用地址空間;
3、線程是在進程的地址空間內部啟動並執行;
4、進程是承擔資源分派的基本單位;線程則是實現資源調度的基本單位;
5、線程環境切換比進程環境切換要快得多。 四、線程操作函數

注意:因為Linux上的線程函數位於libpthread共用庫中,因此在編譯時間要加上-l pthread。例如:

gcc -o test test.c -l pthread
1.建立線程
#include<pthread.h>int pthread_create(pthread_t *thread,const pthread_attr_t* attr,void*(*start routine)(void*),void *arg)

傳回值:成功返回0,失敗時返回錯誤碼。以前學的系統函數都是成功返回0,失敗返回-1,而錯誤碼儲存在全域變數error中,pthread庫的函數都是通過傳回值返回錯誤碼,雖然每個線程也都有一個error,但這是為了相容其他函數介面而提供的,pthread庫本身並不使用它,通過傳回值返回錯誤碼更加清晰。

參數:
thread:指向線程標識符的指標。
arr:用於設定線程的屬性。
start routine:一個函數指標,新興行間的線程從start routine函數的地址開始運行。
arg:一個無類型的指標,當我們需要為第三個參數函數指標傳參時,那麼便需要把這些參數放到一個結構中,然後把這個結構的地址作為arg參數傳入。可以理解為此arg參數就是上面函數指標的參數。
建立線程程式碼範例:

#include<stdio.h>#include<pthread.h>#include<stdlib.h>//新線程,每秒列印一次,列印五次void* thread_run(void *arg){    int count=0;    while(count++<5)    {        sleep(1);        printf("%s,  %d\n",(char*)arg,count);    }    printf("thread is over...\n");    return NULL;}int main(){    //主線程    printf("pthread\n");    pthread_t tid;    int ret=pthread_create(&tid,NULL,thread_run,"thread is running!!!!");    if(ret != 0)    {        printf("pthread_creat error\n");        return -1;    }    else    {        sleep(1);        printf("pthread is running!!\n");    }    int exitCode;    pthread_join(tid,(void**)&exitCode);    printf("main is over..%d\n",exitCode);//新線程的退出碼    return 0;}


上面代碼中用到了一個pthread_join函數,此函數的功能就是等待一個線程的結束。

#include <pthread.h>int pthread_join(pthread_t thread, void **retval);

此例中讓主線程等待新線程的結束。第一個參數為新線程的線程ID,第二個參數用來接收新線程的退出碼。 2.線程的終止

線程終止有三種方式:
簡單的從啟動常式中返回,傳回值是線程的退出嗎碼。上面的例子thread_run函數直接return就是這種方式。

線程可以被同一進程中的其他線程調用pthread_cancle終止。
例如在主線程中終止新線程,仍為上面的例子。pthread_cancle的參數為要結束線程的線程ID。
代碼:

#include<stdio.h>#include<pthread.h>#include<stdlib.h>//新線程,每秒列印一次,列印五次void* thread_run(void *arg){    int count=0;    while(count++<5)    {        sleep(1);        printf("%s,  %d\n",(char*)arg,count);    }    printf("thread is over...\n");    return NULL;}int main(){    //主線程    printf("pthread\n");    pthread_t tid;    int ret=pthread_create(&tid,NULL,thread_run,"thread is running!!!!");    if(ret != 0)    {        printf("pthread_creat error\n");        return -1;    }    else    {        sleep(1);        printf("pthread is running!!\n");    }    pthread_cancel(tid); //主線程中結束子線程    int exitCode;    pthread_join(tid,(void**)&exitCode);    printf("main is over..%d\n",exitCode);//新線程退出碼    return 0;}

執行結果應為主線程列印一次後直接結束,新線程退出碼為-1。如果一個線程被其他線程調用pthread_cancel異常終止掉,它返回的退出碼將是常數PTHREAD_CANCELED。這個宏被定義在pthread.h中,值為-1。

線程可以調用pthread_exit自己終止自己。
pthread_exit的參數為退出碼。注意,pthread_exit的參數或者新線程return的指標所指向的記憶體單元必須是全域的或者由malloc分配的,因為當其他線程pthread_join得到這個返回指標時新線程函數已經退出了。
代碼:

#include<stdio.h>#include<pthread.h>#include<stdlib.h>//新線程,每秒列印一次,列印五次void* thread_run(void *arg){    int count=0;    while(count++<5)    {        sleep(1);        printf("%s,  %d\n",(char*)arg,count);    }    printf("thread is over...\n");    pthread_exit((void*)10);}int main(){    //主線程    printf("pthread\n");    pthread_t tid;    int ret=pthread_create(&tid,NULL,thread_run,"thread is running!!!!");    if(ret != 0)    {        printf("pthread_creat error\n");        return -1;    }    else    {        sleep(1);        printf("pthread is running!!\n");    }    int exitCode;    pthread_join(tid,(void**)&exitCode);    printf("main is over..%d\n",exitCode);//新線程的退出碼    return 0;}


執行結果為:程式正常執行,但新線程退出碼為10。 五、分離線程

一般情況下,線程終止後,資源不會被立即釋放,其終止狀態一直保留到其他線程調用pthread_join擷取它的狀態為止,這時系統擦才會釋放它所佔用的資源。但是線程也可以被置為detach狀態,這樣的線程一旦終止就立刻回收它佔用額度所有資源,而不保留終止狀態,這時主線程也不必一直阻塞等待,可以去做其他的工作。不能對一個已經處於detach狀態的線程調用pthread_join,這樣的調用將返回EINVAL。對一個detach的線程調用pthread_join或者pthread_detach都可以把該線程置為detach狀態,也就是說,不能對同一線程調用兩次pthread_join,或者如果已經對一個線程調用了pthread_detach就不能再調用pthread_join了。

線程是可分離的(detached)或者結合的(joinable),一個可結合的線程能夠被其他線程收回其資源和殺死。在被其他線程回收之前,他的儲存空間資源(eg:棧)是不可釋放的。相反一個分離的線程是不能被其他線程回收或殺死的,它的儲存空間資源在它終止時由系統自動釋放。
預設情況下,線程被建立成可結合的。為了避免記憶體的泄露,每個可結合線程都應該被顯示的回收,即調用pthread_join。若沒有被join,則會造成資源,記憶體的泄露。

因為調用pthread_join後,如果應該被join的新線程沒有運行結束,調用者會被阻塞,我們有時候並不希望如此。這時可在新線程中加入代碼pthread_detach(pthread_self())或者主線程調用pthread_detach(thread_id)來將新線程設定成可分離的,如此一來,新線程運行結束後會自動釋放所有資源。

代碼:

#include<stdio.h>#include<pthread.h>#include<stdlib.h>//新線程,每秒列印一次,列印五次void* thread_run(void *arg){    pthread_detach(pthread_self());    printf("%s\n",(char*)arg);    return NULL;}int main(){    //主線程    printf("pthread\n");    pthread_t tid;    int ret=pthread_create(&tid,NULL,thread_run,"thread is running!!");    if(ret != 0)    {        printf("pthread_creat error\n");        return -1;    }    //wait    int ret1=0;    sleep(1);    if(0== pthread_join(tid,NULL))    {        printf("pthread wait success!\n");        ret1 = 0;    }    else    {        printf("pthread wait failed!\n");        ret1 = 1;    }    return ret1;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.