2014-01-23 53 views
3

所以我搜索了堆棧溢出和其他資源的高低,但我無法理解關於上述功能的一些事情。具體而言,pthread_cond_timedwait()&pthread_cond_broadcast()說明

1)當pthread_cond_timedwait()由於定時器值已用完而返回時,它如何自動重新獲取互斥鎖。該互斥鎖可能會在其他地方被鎖定。例如,在生產者 - 消費者隊列中,消費者可能正在等待使用timedwait()變體。從我讀過的解釋中可以看出,當線程喚醒時,互斥鎖會自動重新獲取。這讓我感到困惑?還是在計時器耗盡後它會被喚醒,然後再次檢查謂詞並鎖定。這是沒有意義的?

2)當一堆線程已經獲得一個互斥量,並且現在都在等待一個簡單的pthread_cond_wait()時,如果另一個線程發出pthread_cond_broadcast(),會發生什麼情況。每個線程(由調度程序確定)是否會逐個喚醒,按順序獲取互斥鎖,然後每個線程都繼續?或者只有整個線程列表中的一個線程被喚醒。我假設這兩種行爲中的後者也可以使用pthread_cond_signal()。另外,如果以前的方法是正確的行爲,那麼我們可以假設其他一些線程可能最終會在其他地方的變量上調用wait()。那麼這會使所有其他等待線程回到阻塞狀態並等待一個信號。或者他們每個人都會繼續醒來並逐漸取得進展?

回答

0

如果由於超時到期而返回pthread_cond_timedwait(),它將在返回之前重新獲取互斥鎖。這可能意味着它必須等待互斥鎖被解鎖,如果當時被另一個線程鎖定。基本上,它的行爲就好像它在返回之前調用pthread_mutex_lock()

當調用pthread_cond_broadcast()時,所有等待的線程都會被喚醒,這意味着它們都會嘗試獲取互斥鎖並返回。當然,互斥量會將它串連起來,所以它們只會一次返回。在這一點之後會發生什麼並不重要 - 只要這些線程能夠獲取互斥體,它們最終都會從它們的pthread_cond_wait()呼叫中返回。另一個調用pthread_cond_wait()的線程不會影響這個。

2

(1)那麼pthread_cond_timedwait()

短(淺)解釋它是如何工作的。

1)與pthread_cond_timewait()關聯的互斥鎖應在函數調用之前鎖定。這是你的責任。否則,函數行爲是未定義的。

2)當程序將其控件傳遞給函數時,函數ATOMICALLY釋放相關的互斥量,使其他線程有機會獲取它。當你在等待時,互斥鎖被解鎖。解鎖它是功能責任。 如果函數實現不能這樣做,只有一個線程會處理關聯的互斥鎖。

3)當函數返回時,無論是作爲超時的結果還是作爲接收信號的結果,函數都會原子鎖定互斥鎖。鎖定互斥鎖是功能責任。

4)現在互斥體應該再次由您解鎖。

解釋中的「原子」一詞意味着函數本身是線程安全的。

(2)調用pthread_cond_broadcast()

與調用pthread_cond_broadcast信令()使得所有等待的線程醒來並開始處理一個接一個。用pthread_cond_signal()發信令只喚醒一個線程。用下面的代碼來「感受」你可能玩的概念,以說明這個想法。用pthread_cond_brodcast替換pthread_cons_signal。考慮到使用pthread_cons_signal時程序永遠不會終止:只有一個服務器線程獲取信號並從等待循環中退出。

#include <stdio.h> 
#include <stdlib.h> 
#include <pthread.h> 
#include <unistd.h> 

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 
int value = 0; 

void* waiter(void* arg) 
{ 
    int* tid = (int*)arg; 

    printf("waiter started %d\n", *tid); 

    pthread_mutex_lock(&mutex); 
    while(value == 0) 
    { 
    pthread_cond_wait(&cond, &mutex); 
    } 
    sleep(10); 
    printf("waiter %d releases\n", *tid); 
    pthread_mutex_unlock(&mutex); 

} 

void* notifier(void* arg) 
{ 
    sleep(2); 
    pthread_mutex_lock(&mutex); 
    value = 1; 
    //pthread_cond_broadcast(&cond); 
    pthread_cond_signal(&cond); 
    pthread_mutex_unlock(&mutex); 
} 

int main(void) 
{ 
    pthread_t w1; // waiter 
    int tid1=1; 
    pthread_t w2; // waiter 
    int tid2=2; 
    pthread_t n1; // notifier 

    pthread_create(&w1, NULL, waiter, &tid1); 
    pthread_create(&w2, NULL, waiter, &tid2); 
    pthread_create(&n1, NULL, notifier, NULL); 

    pthread_join(w1, NULL); 
    pthread_join(w2, NULL); 
    pthread_join(n1, NULL); 
    return 0; 
}