linux下C語言多線程(五)雜項函數

在Posix線程規範中還有幾個輔助函數難以歸類,暫且稱其爲雜項函數,主要包括pthread_self()、pthread_equal()和pthread_once()三個,另外還有一個LinuxThreads非可移植性擴展函數pthread_kill_other_threads_np()。本文就介紹這幾個函數的定義和使用。
1. 獲得本線程ID
pthread_t pthread_self(void)

本函數返回本線程的標識符。

在LinuxThreads中,每個線程都用一個pthread_descr結構來描述,其中包含了線程狀態、線程ID等所有需要的數據結構,此函數的實現就是在線程棧幀中找到本線程的pthread_descr結構,然後返回其中的p_tid項。

pthread_t類型在LinuxThreads中定義爲無符號長整型。

2. 判斷兩個線程是否爲同一線程
int pthread_equal(pthread_t thread1, pthread_t thread2)

判斷兩個線程描述符是否指向同一線程。在LinuxThreads中,線程ID相同的線程必然是同一個線程,因此,這個函數的實現僅僅判斷thread1和thread2是否相等。

3. 僅執行一次的操作
int pthread_once(pthread_once_t *once_control, void (*init_routine) (void))

本函數使用初值爲PTHREAD_ONCE_INIT的once_control變量保證init_routine()函數在本進程執行序列中僅執行一次。
#include <stdio.h>
#include <pthread.h>

pthread_once_t once=PTHREAD_ONCE_INIT;

void once_run(void)
{
printf("once_run in thread %d\n",pthread_self());
}

void * child1(void *arg)
{
int tid=pthread_self();
printf("thread %d enter\n",tid);
pthread_once(&once,once_run);
printf("thread %d returns\n",tid);
}

void * child2(void *arg)
{
int tid=pthread_self();
printf("thread %d enter\n",tid);
pthread_once(&once,once_run);
printf("thread %d returns\n",tid);
}

int main(void)
{
int tid1,tid2;

printf("hello\n");
pthread_create(&tid1,NULL,child1,NULL);
pthread_create(&tid2,NULL,child2,NULL);
sleep(10);
printf("main thread exit\n");
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。

4. pthread_kill_other_threads_np()
void pthread_kill_other_threads_np(void)

這個函數是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()是一樣的,其中原因目前還不清楚。
發佈了4 篇原創文章 · 獲贊 13 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章