2012-01-23 42 views
3

試圖實施兩名平行工作者。形成數據後,我需要告訴工作人員採集數據並對其進行處理。這裏是代碼:如何使用pthread_cond_signal和pthread_cond_wait正確地使pthreads工作?

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

void *worker(void *data); 

struct worker_data_t 
{ 
    pthread_t thread_id; 
    pthread_mutex_t mutex; 
    pthread_cond_t cond; 
    long id, data; 
}; 

struct worker_data_t *workers_data; 

int main(int argc, char **argv) 
{ 
    int cpus = sysconf(_SC_NPROCESSORS_ONLN); 
    if (cpus < 1) 
     cpus = 1; 

    workers_data = (struct worker_data_t *)malloc(cpus * sizeof(struct worker_data_t)); 
    int ret_val[cpus]; 

    for (int i = 0; i < cpus; i++) 
    { 
     pthread_mutex_init(&workers_data[i].mutex, NULL); 
     pthread_cond_init(&workers_data[i].cond, NULL); 
     workers_data[i].id = i; 
    } 

    for (int i = 0; i < cpus; i++) 
     ret_val[i] = pthread_create(&workers_data[i].thread_id, NULL, worker, &workers_data[i]); 

    pthread_mutex_lock(&workers_data[0].mutex); 
    pthread_cond_signal(&workers_data[0].cond); 
    pthread_mutex_unlock(&workers_data[0].mutex); 

    pthread_mutex_lock(&workers_data[0].mutex); 
    pthread_cond_signal(&workers_data[0].cond); 
    pthread_mutex_unlock(&workers_data[0].mutex); 

    for (int i = 0; i < cpus; i++) 
     pthread_join(workers_data[i].thread_id, NULL); 

    return 0; 
} 

void *worker(void *data) 
{ 
    struct worker_data_t d = *((struct worker_data_t*)(data)); 
    printf("Thread %d started\n", d.id); 
    for (;;) 
    { 
     pthread_mutex_lock(&workers_data[d.id].mutex); 
     pthread_cond_wait(&workers_data[d.id].cond, &workers_data[d.id].mutex); 
     printf("catch!\n"); 
     pthread_mutex_unlock(&workers_data[d.id].mutex); 
    } 
} 

在通過pthread_cond_signal通知worker後沒有任何反應。如果我在每個pthread_cond_signal塊之前放置睡眠(1),它就會起作用。

應該怎麼做才能讓它在沒有睡眠的情況下工作?

回答

2

正如R.所說的,而且他應該做出回答,你需要的是一個謂詞。這是你測試的事情,看看條件是否屬實。

在你的情況下,它應該是一個簡單的變量,由workers_data[0].mutex保護。

然後在你的worker中,像你已經做的那樣鎖定互斥鎖,然後檢查謂詞。如果謂詞是真的,你不需要等待條件,所以不要。只要去做你需要做的事情。如果謂詞是假的,則等待條件。

不要忘記的一點非常重要的一點是謂詞決不能在條件變量使用的互斥鎖之外進行更改。如果是這樣,在某些情況下會錯過條件,這會導致線程卡住。

1

當在該調用引用的condvar上沒有鎖定線程時,由pthread_cond_signal()生成的信號將丟失。這是極有可能會發生以下情況:

  1. main()線程調用pthread_create()
  2. main()線程執行1個或多個鎖定信號解鎖塊
  3. 子線程獲取處理器時間和被鎖定在pthread_cond_wait()。信號已經丟失,所以它們永遠不會被喚醒

如果一個線程在pthread_create()的調用之後立即得到CPU,那麼它是不確定的。當您在發出信號之前執行sleep(1)時,您可以讓工作線程執行並開始監聽它們的condvars。這是解決問題的方法之一。您仍然可能需要執行某種準備檢查以確保工作人員正在等待,並且您的信號不會丟失(例如,創建另一個condvar並在員工準備就緒時發出信號)。另一種方法是使用信號量。

另外請記住,pthread_join()將永遠不會在您的程序中返回,因爲工作人員無法離開無限循環。也建議檢查每個pthread_...()回報是否有錯誤,特別是當您調查某種意外的程序行爲時。

+2

雖然這個答案充滿了正確的信息,但它並沒有解決最重要的問題,即條件變量**永遠不能在沒有關聯謂詞**的情況下使用。 –

相關問題