這是一個關於Posix線程編程的專欄。做者在闡明概念的基礎上,將向您詳細講述Posix線程庫API。本文是第五篇將向您講述pthread_self()、pthread_equal()和pthread_once()等雜項函數。
在Posix線程規範中還有幾個輔助函數難以歸類,暫且稱其爲雜項函數,主要包括pthread_self()、pthread_equal()和pthread_once()三個,另外還有一個LinuxThreads非可移植性擴展函數pthread_kill_other_threads_np()。本文就介紹這幾個函數的定義和使用。
本函數返回本線程的標識符。
在LinuxThreads中,每一個線程都用一個pthread_descr結構來描述,其中包含了線程狀態、線程ID等全部須要的數據結構,此函數的實現就是在線程棧幀中找到本線程的pthread_descr結構,而後返回其中的p_tid項。
pthread_t類型在LinuxThreads中定義爲無符號長整型。
判斷兩個線程描述符是否指向同一線程。在LinuxThreads中,線程ID相同的線程必然是同一個線程,所以,這個函數的實現僅僅判斷thread1和thread2是否相等。
3.僅執行一次的操做
int pthread_once(pthread_once_t *once_control, void (*init_routine) (void))
本函數使用初值爲PTHREAD_ONCE_INIT的once_control變量保證init_routine()函數在本進程執行序列中僅執行一次。
#i nclude <stdio.h>
#i nclude <pthread.h>
pthread_once_t once=PTHREAD_ONCE_INIT;
void once_run(void)
{
printf("once_run in thread %dn",pthread_self());
}
void * child1(void *arg)
{
int tid=pthread_self();
printf("thread %d entern",tid);
pthread_once(&once,once_run);
printf("thread %d returnsn",tid);
}
void * child2(void *arg)
{
int tid=pthread_self();
printf("thread %d entern",tid);
pthread_once(&once,once_run);
printf("thread %d returnsn",tid);
}
int main(void)
{
int tid1,tid2;
printf("hellon");
pthread_create(&tid1,NULL,child1,NULL);
pthread_create(&tid2,NULL,child2,NULL);
sleep(10);
printf("main thread exitn");
return 0;
} |
once_run()函數僅執行一次,且究竟在哪一個線程中執行是不定的,儘管pthread_once(&once,once_run)出如今兩個線程中。
LinuxThreads使用互斥鎖和條件變量保證由pthread_once()指定的函數執行且僅執行一次,而once_control則表徵是否執行過。若是once_control的初值不是PTHREAD_ONCE_INIT(LinuxThreads定義爲0),pthread_once()的行爲就會不正常。在LinuxThreads中,實際"一次性函數"的執行狀態有三種:NEVER(0)、IN_PROGRESS(1)、DONE(2),若是once初值設爲1,則因爲全部pthread_once()都必須等待其中一個激發"已執行一次"信號,所以全部pthread_once()都會陷入永久的等待中;若是設爲2,則表示該函數已執行過一次,從而全部pthread_once()都會當即返回0。
這個函數是LinuxThreads針對自己沒法實現的POSIX約定而作的擴展。POSIX要求當進程的某一個線程執行exec*系統調用在進程空間中加載另外一個程序時,當前進程的全部線程都應終止。因爲LinuxThreads的侷限性,該機制沒法在exec中實現,所以要求線程執行exec前手工終止其餘全部線程。pthread_kill_other_threads_np()的做用就是這個。
須要注意的是,pthread_kill_other_threads_np()並無經過pthread_cancel()來終止線程,而是直接向管理線程發"進程退出"信號,使全部其餘線程都結束運行,而不通過Cancel動做,固然也不會執行退出回調函數。儘管LinuxThreads的實驗結果與文檔說明相同,但代碼實現中倒是用的__pthread_sig_cancel信號來kill線程,應該效果與執行pthread_cancel()是同樣的,其中緣由目前還不清楚。