一、技術都是爲了解決實際問題的,考慮下面的場景:
主線程建立一個子線程,子線程作一些任務,在主線程上,等待子線程完成任務,而後向下運行。代碼以下:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void* FuncA(void* arg)
{
printf("FuncA Time[%d]\n", time(NULL));
sleep(2);
}
int main(int argc,char* argv[])
{
pthread_t threadA;
pthread_create(&threadA, NULL, FuncA, NULL);
pthread_join(threadA,NULL);
printf("main Time[%d]\n", time(NULL));
getchar();
return 0;
}
[niu_zibin@localhost thread]$ g++ -o main main.cpp -lpthread
[niu_zibin@localhost thread]$ ./main
FuncA Time[1477297071]
main Time[1477297073]
二、能夠看到,主線程阻塞在pthread_join,那麼問題來了,如何讓主線程不阻塞在pthread_join呢?
三、上面產生的緣由是:默認建立的線程A不是分離的,也就是被主線程關聯。
所以,解決辦法是:建立線程A的時候,把它設置成分離的,再也不被別的線程關聯。以下:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void* FuncA(void* arg)
{
printf("First FuncA Time[%d]\n", time(NULL));
sleep(2);
printf("Second FuncA Time[%d]\n", time(NULL));
}
int main(int argc,char* argv[])
{
pthread_t threadA;
pthread_attr_t pAttr;
pthread_attr_init(&pAttr);
pthread_attr_setdetachstate(&pAttr,PTHREAD_CREATE_DETACHED);
pthread_create(&threadA, &pAttr, FuncA, NULL);
int ret = pthread_join(threadA,NULL);
printf("pthread_join ret[%d]\n",ret);
printf("main Time[%d]\n", time(NULL));
getchar();
return 0;
}
[niu_zibin@localhost thread]$ g++ -o main main.cpp -lpthread
[niu_zibin@localhost thread]$ ./main
pthread_join ret[22]
main Time[1477298407]
First FuncA Time[1477298407]
Second FuncA Time[1477298409]
再也不阻塞。
四、注意:設置了分離狀態【PTHREAD_CREATE_DETACHED】,pthread_join返回錯誤。
改爲可結合狀態【PTHREAD_CREATE_JOINABLE】,pthread_join返回成功,以下:
pthread_attr_setdetachstate(&pAttr,PTHREAD_CREATE_JOINABLE);
[niu_zibin@localhost thread]$ g++ -o main main.cpp -lpthread
[niu_zibin@localhost thread]$ ./main
First FuncA Time[1477298637]
Second FuncA Time[1477298639]
pthread_join ret[0]
main Time[1477298639]
五、還有一種辦法,就是建立線程A以後,也就是在線程A運行的時候,進行分離操做,以下:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void* FuncA(void* arg)
{
printf("First FuncA Time[%d]\n", time(NULL));
sleep(2);
printf("Second FuncA Time[%d]\n", time(NULL));
}
int main(int argc,char* argv[])
{
pthread_t threadA;
pthread_create(&threadA, NULL, FuncA, NULL);
pthread_detach(threadA);
pthread_join(threadA,NULL);
printf("main Time[%d]\n", time(NULL));
getchar();
return 0;
}
[niu_zibin@localhost thread]$ g++ -o main main.cpp -lpthread
[niu_zibin@localhost thread]$ ./main
main Time[1477298924]
First FuncA Time[1477298924]
Second FuncA Time[1477298926]
六、線程是可結合(joinable)或者分離的(detached)。
對於可結合線程A,被主線程回收資源(好比A的線程棧)和殺死,在主線程join線程A以前,線程A的資源是不會被釋放的。
對於分離式線程A,在它終止後,系統會自動釋放線程A的資源。
七、對於分離式線程A,考慮一種極端的狀況,分離式線程執行特別快,在pthread_create返回以前就已經終止了。
這就意味着,pthread_create返回的數據是垃圾數據。
八、怎麼解決上面的問題?
在分離式線程A中執行pthread_cond_timewait函數,讓當前線程等待一會,確保pthread_create返回的時候,當前線程尚未終止。
還有一種辦法,使用PV操做,分離式線程內先執行P操做,卡在這裏。在主線程pthread_create以後進行V操做,
從而確保pthread_create以後,分離式線程剛開始執行。