linux下多線程的建立與等待詳解

來源:互聯網
上載者:User

 

linux下多線程的建立與等待詳解

 

所有線程都有一個線程號,也就是Thread ID。其類型為pthread_t。通過調用pthread_self()函數可以獲得自身的線程號。
下面說一下如何建立一個線程。
通過建立線程,線程將會執行一個線程函數,該線程格式必須按照下面來聲明:
void * Thread_Function(void *)
建立線程的函數如下:

int pthread_create(pthread_t *restrict thread,
       const pthread_attr_t *restrict attr,
       void *(*start_routine)( void*),  void *restrict arg);

下面說明一下各個參數的含義:
thread:所建立的線程號。
attr:所建立的線程屬性,這個將在後面詳細說明。
start_routine:即將啟動並執行線程函數。
art:傳遞給線程函數的參數。
下面是一個簡單的建立線程例子:

# include <pthread.h>
# include <stdio.h>
/* Prints x’s to stderr. The parameter is unused. Does not return. */
void* print_xs ( void* unused)
{
     while (1)
    fputc (‘x’, stderr);
     return NULL;
}
/* The main program. */
int main ()
{
    pthread_t thread_id;
    /* Create a new thread. The new thread will run the print_xs
    function. */
    pthread_create (&thread_id, NULL, &print_xs, NULL);
    /* Print o’s continuously to stderr. */
     while (1)
    fputc (‘o’, stderr);
     return 0;
}

在編譯的時候需要注意,由於線程建立函數在libpthread.so庫中,所以在編譯命令中需要將該庫匯入。命令如下:
gcc –o createthread –lpthread createthread.c
如果想傳遞參數給線程函數,可以通過其參數arg,其類型是void *。如果你需要傳遞多個參數的話,可以考慮將這些參數組成一個結構體來傳遞。另外,由於類型是void *,所以你的參數不可以被提前釋放掉。
下面一個問題和前面建立線程類似,不過帶來的問題迴避進程要嚴重得多。如果你的主線程,也就是main函數執行的那個線程,在你其他線程推出之前就已經退出,那麼帶來的bug則不可估量。通過pthread_join函數會讓主線程阻塞,直到所有線程都已經退出。

pthread_join:使一個線程等待另一個線程結束。
代碼中如果沒有pthread_join主線程會很快結束從而使整個進程結束,從而使建立的線程沒有機會開始執行就結束了。加入pthread_join後,主線程會一直等待直到等待的線程結束自己才結束,使建立的線程有機會執行。

int pthread_join(pthread_t thread,  void **value_ptr);

thread:等待退出線程的線程號。
value_ptr:退出線程的傳回值。
下面一個例子結合上面的內容:

int main ()
{
    pthread_t thread1_id;
    pthread_t thread2_id;
     struct char_print_parms thread1_args;
     struct char_print_parms thread2_args;
    /* Create a new thread to print 30,000 x’s. */
    thread1_args.character = ’x’;
    thread1_args.count = 30000;
    pthread_create (&thread1_id, NULL, &char_print, &thread1_args);
    /* Create a new thread to print 20,000 o’s. */
    thread2_args.character = ’o’;
    thread2_args.count = 20000;
    pthread_create (&thread2_id, NULL, &char_print, &thread2_args);
    /* Make sure the first thread has finished. */
    pthread_join (thread1_id, NULL);
    /* Make sure the second thread has finished. */
    pthread_join (thread2_id, NULL);
    /* Now we can safely return. */
     return 0;
}

下面說一下前面提到的線程屬性。
在我們前面提到,可以通過pthread_join()函數來使主線程阻塞等待其他線程退 出,這樣主線程可以清理其他線程的環境。但是還有一些線程,更喜歡自己來清理退出的狀態,他們也不願意主線程調用pthread_join來等待他們。我 們將這一類線程的屬性稱為detached。如果我們在調用pthread_create()函數的時候將屬性設定為NULL,則表明我們希望所建立的線 程採用預設的屬性,也就是jionable。如果需要將屬性設定為detached,則參考下面的例子:

# include <stdio.h>
# include <pthread.h>
void * start_run( void * arg)
{
//do some work
}
int main()
{
    pthread_t thread_id;
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
    pthread_create(&thread_id,&attr,start_run,NULL);
    pthread_attr_destroy(&attr);
    sleep(5);
    exit(0);
}

線上程設定為joinable後,可以調用pthread_detach()使之成為detached。但是相反的操作則不可以。還有,如果線程已經調用pthread_join()後,則再調用pthread_detach()則不會有任何效果。
線程可以通過自身執行結束來結束,也可以通過調用pthread_exit()來結束線程的執行。另外,線程甲可以被線程乙被動結束。這個通過調用pthread_cancel()來達到目的。

int pthread_cancel(pthread_t thread);

函數調用成功返回0。
當然,線程也不是被動的被別人結束。它可以通過設定自身的屬性來決定如何結束。
線程的被動結束分為兩種,一種是非同步終結,另外一種是同步終結。非同步終結就是當其他線程調用 pthread_cancel的時候,線程就立刻被結束。而同步終結則不會立刻終結,它會繼續運行,直到到達下一個結束點(cancellation point)。當一個線程被按照預設的建立方式建立,那麼它的屬性是同步終結。
通過調用pthread_setcanceltype()來設定終結狀態。

int pthread_setcanceltype( int type,  int *oldtype);

state:要設定的狀態,可以為PTHREAD_CANCEL_DEFERRED或者為PTHREAD_CANCEL_ASYNCHRONOUS。
那麼前面提到的結束點又是如何設定了?最常用的建立終結點就是調用pthread_testcancel()的地方。該函數除了檢查同步終結時的狀態,其他什麼也不做。
上面一個函數是用來設定終結狀態的。還可以通過下面的函數來設定終結類型,即該線程可不可以被終結:

int pthread_setcancelstate( int state,  int *oldstate);

state:終結狀態,可以為PTHREAD_CANCEL_DISABLE或者PTHREAD_CANCEL_ENABLE。具體什麼含義大家可以通過單詞意思即可明白。
最後說一下線程的本質。其實在Linux中,建立的線程並不是在原先的進程中,而是系統通過 一個系統調用clone()。該系統copy了一個和原先進程完全一樣的進程,並在這個進程中執行線程函數。不過這個copy過程和fork不一樣。 copy後的進程和原先的進程共用了所有的變數,運行環境。這樣,原先進程中的變數變動在copy後的進程中便能體現出來。

轉載請註明出處。http://www.vimer.cn/

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.