1、技術都是為了解決實際問題的,考慮下面的場景:
主線程建立一個子線程,子線程做一些任務,在主線程上,等待子線程完成任務,然後向下運作。代碼如下:
#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]
2、可以看到,主線程阻塞在pthread_join,那麼問題來了,如何讓主線程不阻塞在pthread_join呢?
3、上面産生的原因是:預設建立的線程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]
不再阻塞。
4、注意:設定了分離狀态【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]
5、還有一種辦法,就是建立線程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]
6、線程是可結合(joinable)或者分離的(detached)。
對于可結合線程A,被主線程回收資源(比如A的線程棧)和殺死,在主線程join線程A之前,線程A的資源是不會被釋放的。
對于分離式線程A,在它終止後,系統會自動釋放線程A的資源。
7、對于分離式線程A,考慮一種極端的情況,分離式線程執行特别快,在pthread_create傳回之前就已經終止了。
這就意味着,pthread_create傳回的資料是垃圾資料。
8、怎麼解決上面的問題?
在分離式線程A中執行pthread_cond_timewait函數,讓目前線程等待一會,確定pthread_create傳回的時候,目前線程還沒有終止。
還有一種辦法,使用PV操作,分離式線程内先執行P操作,卡在這裡。在主線程pthread_create之後進行V操作,
進而確定pthread_create之後,分離式線程剛開始執行。