日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

pthread_join

發(fā)布時(shí)間:2025/3/21 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 pthread_join 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(zhuǎn)http://cache.baidu.com/c?m=9d78d513d98107f518bac7281a17a7711e2097624c8f8d4e23c0d408cd6b01070124f4ba543f0d4196806b6776f11200adba60297c5737b7ec99d515c0ffc97f6adb67722b4dd81605d36eed910432c054cb0cfeae6fe4b8f23495a5&p=91759a42d6df12a058f7db3a574b&user=baidu

pthread_join使一個(gè)線程等待另一個(gè)線程結(jié)束。

代碼中如果沒有pthread_join主線程會很快結(jié)束從而使整個(gè)進(jìn)程結(jié)束,從而使創(chuàng)建的線程沒有機(jī)會開始執(zhí)行就結(jié)束了。加入pthread_join后,主線程會一直等待直到等待的線程結(jié)束自己才結(jié)束,使創(chuàng)建的線程有機(jī)會執(zhí)行。

所有線程都有一個(gè)線程號,也就是Thread ID。其類型為pthread_t。通過調(diào)用pthread_self()函數(shù)可以獲得自身的線程號。

下面說一下如何創(chuàng)建一個(gè)線程。

通過創(chuàng)建線程,線程將會執(zhí)行一個(gè)線程函數(shù),該線程格式必須按照下面來聲明:

void * Thread_Function(void *)

創(chuàng)建線程的函數(shù)如下:

QUOTE:
int pthread_create(pthread_t *restrict thread,

const pthread_attr_t *restrict attr,

void *(*start_routine)(void*), void *restrict arg);


下面說明一下各個(gè)參數(shù)的含義:

thread:所創(chuàng)建的線程號。

attr:所創(chuàng)建的線程屬性,這個(gè)將在后面詳細(xì)說明。

start_routine:即將運(yùn)行的線程函數(shù)。

art:傳遞給線程函數(shù)的參數(shù)。

下面是一個(gè)簡單的創(chuàng)建線程例子:

QUOTE:
#include

#include



void* print_xs (void* unused)

{

while (1)

fputc (‘x’, stderr);

return NULL;

}



int main ()

{

pthread_t thread_id;



pthread_create (&thread_id, NULL, &print_xs, NULL);



while (1)

fputc (‘o’, stderr);

return 0;

}


在編譯的時(shí)候需要注意,由于線程創(chuàng)建函數(shù)在libpthread.so庫中,所以在編譯命令中需要將該庫導(dǎo)入。命令如下:

gcc –o createthread –lpthread createthread.c

如果想傳遞參數(shù)給線程函數(shù),可以通過其參數(shù)arg,其類型是void *。如果你需要傳遞多個(gè)參數(shù)的話,可以考慮將這些參數(shù)組成一個(gè)結(jié)構(gòu)體來傳遞。另外,由于類型是void *,所以你的參數(shù)不可以被提前釋放掉。

下面一個(gè)問題和前面創(chuàng)建進(jìn)程類似,不過帶來的問題回避進(jìn)程要嚴(yán)重得多。如果你的主線程,也就是main函數(shù)執(zhí)行的那個(gè)線程,在你其他縣城推出之前就已經(jīng)退出,那么帶來的bug則不可估量。通過pthread_join函數(shù)會讓主線程阻塞,直到所有線程都已經(jīng)退出。

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

thread:等待退出線程的線程號。

value_ptr:退出線程的返回值。

下面一個(gè)例子結(jié)合上面的內(nèi)容:

QUOTE:
int main ()

{

pthread_t thread1_id;

pthread_t thread2_id;

struct char_print_parms thread1_args;

struct char_print_parms thread2_args;



thread1_args.character = ’x’;

thread1_args.count = 30000;

pthread_create (&thread1_id, NULL, &char_print, &thread1_args);



thread2_args.character = ’o’;

thread2_args.count = 20000;

pthread_create (&thread2_id, NULL, &char_print, &thread2_args);



pthread_join (thread1_id, NULL);



pthread_join (thread2_id, NULL);



return 0;

}


下面說一下前面提到的線程屬性。

在我們前面提到,可以通過pthread_join()函數(shù)來使主線程阻塞等待其他線程退出,這樣主線程可以清理其他線程的環(huán)境。但是還有一些線程,更喜歡自己來清理退出的狀態(tài),他們也不愿意主線程調(diào)用pthread_join來等待他們。我們將這一類線程的屬性稱為detached。如果我們在調(diào)用pthread_create()函數(shù)的時(shí)候?qū)傩栽O(shè)置為NULL,則表明我們希望所創(chuàng)建的線程采用默認(rèn)的屬性,也就是jionable。如果需要將屬性設(shè)置為detached,則參考下面的例子:

QUOTE:
#include

#include

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);

}


在線程設(shè)置為joinable后,可以調(diào)用pthread_detach()使之成為detached。但是相反的操作則不可以。還有,如果線程已經(jīng)調(diào)用pthread_join()后,則再調(diào)用pthread_detach()則不會有任何效果。

線程可以通過自身執(zhí)行結(jié)束來結(jié)束,也可以通過調(diào)用pthread_exit()來結(jié)束線程的執(zhí)行。另外,線程甲可以被線程乙被動結(jié)束。這個(gè)通過調(diào)用pthread_cancel()來達(dá)到目的。

int pthread_cancel(pthread_t thread);

函數(shù)調(diào)用成功返回0。

當(dāng)然,線程也不是被動的被別人結(jié)束。它可以通過設(shè)置自身的屬性來決定如何結(jié)束。

線程的被動結(jié)束分為兩種,一種是異步終結(jié),另外一種是同步終結(jié)。異步終結(jié)就是當(dāng)其他線程調(diào)用pthread_cancel的時(shí)候,線程就立刻被結(jié)束。而同步終結(jié)則不會立刻終結(jié),它會繼續(xù)運(yùn)行,直到到達(dá)下一個(gè)結(jié)束點(diǎn)(cancellation point)。當(dāng)一個(gè)線程被按照默認(rèn)的創(chuàng)建方式創(chuàng)建,那么它的屬性是同步終結(jié)。

通過調(diào)用pthread_setcanceltype()來設(shè)置終結(jié)狀態(tài)。

int pthread_setcanceltype(int type, int *oldtype);

state:要設(shè)置的狀態(tài),可以為PTHREAD_CANCEL_DEFERRED或者為PTHREAD_CANCEL_ASYNCHRONOUS。

那么前面提到的結(jié)束點(diǎn)又是如何設(shè)置了?最常用的創(chuàng)建終結(jié)點(diǎn)就是調(diào)用pthread_testcancel()的地方。該函數(shù)除了檢查同步終結(jié)時(shí)的狀態(tài),其他什么也不做。

上面一個(gè)函數(shù)是用來設(shè)置終結(jié)狀態(tài)的。還可以通過下面的函數(shù)來設(shè)置終結(jié)類型,即該線程可不可以被終結(jié):

int pthread_setcancelstate(int state, int *oldstate);

state:終結(jié)狀態(tài),可以為PTHREAD_CANCEL_DISABLE或者PTHREAD_CANCEL_ENABLE。具體什么含義大家可以通過單詞意思即可明白。

最后說一下線程的本質(zhì)。其實(shí)在Linux中,新建的線程并不是在原先的進(jìn)程中,而是系統(tǒng)通過一個(gè)系統(tǒng)調(diào)用clone()。該系統(tǒng)copy了一個(gè)和原先進(jìn)程完全一樣的進(jìn)程,并在這個(gè)進(jìn)程中執(zhí)行線程函數(shù)。不過這個(gè)copy過程和fork不一樣。copy后的進(jìn)程和原先的進(jìn)程共享了所有的變量,運(yùn)行環(huán)境。這樣,原先進(jìn)程中的變量變動在copy后的進(jìn)程中便能體現(xiàn)出來。

總結(jié)

以上是生活随笔為你收集整理的pthread_join的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。