2017-05-27 60 views
0

主線程產生> 1個線程,並且它們每個都可以返回一個錯誤值。如果發生這種情況,其他線程繼續進行是沒有意義的,因此應該取消它們。如何加入任何線程先完成?

所以,我想我的主線程:

  • 加入與哪個線程首先完成;
  • 檢查此線程是否返回了錯誤,如果是,請取消所有其他線程。

但是,pthread_join要求我指定要加入哪個線程。如果我打電話,例如,pthread_join(thread1, thread1_ret)thread2完成,出現錯誤,那麼我將無法知道thread2完成了錯誤之前thread1完成,而且完成thread2過早很可能會意味着thread1目前正在等待事實一個永遠不會被髮信號的條件變量,因爲只有thread2可能表示該變量...所以,不好。

我想我的主線程取消thread1如果thread2完成,反之亦然。

如何做到這一點?

回答

1

如何做到這一點?

您需要一個單獨的通信通道。

一個典型的解決方案涉及一個隊列(成品線程)和一個條件變量。

完成錯誤的線程將自己放入隊列並在返回之前指示條件。主線程等待條件,檢查隊列,並加入它在那裏找到的線程,然後取消所有其他線程。

還要注意,異步線程取消很難正確地進行。它通常是最好有一個全局變量,所有線程定期檢查:while (!exit_requested) { do_work(); }

0

你想是這樣的:

struct thread_data { 
    int stop; 
    pthread_cond_t * flag; 
    pthread_mutex_t * lock; 
    int * failCount; 
    int * successCount; 
}; 

void * foobar(void * ptr) 
{ 
    struct thread_data * data = (struct thread_data*)ptr; 
    int fail = 0; 
    while (isWorkToBeDone() && !data->stop) { 
    // do some work 

    if (encounteredError()) { 
     pthread_mutex_lock(data->lock); 
     data->failCount += 1; 
     fail = 1; 
     pthread_cond_signal(data->flag); 
     pthread_mutex_unlock(data->lock); 
    } 
    } 

    // clean up 
    if (!fail) { 
    pthread_mutex_lock(data->lock); 
    data->successCount += 1; 
    pthread_cond_signal(data->flag); 
    pthread_mutex_unlock(data->lock); 
    } 

    pthread_exit(NULL); 
} 


int runThreads() 
{ 
    pthread_t * threads; 

    pthread_mutex_t lock; 
    pthread_cond_t flag; 

    int i; 
    struct thread_data data; 

    threads = malloc(sizeof(*threads)*numThreads); 
    if (!threads) { 
    // handle malloc error 
    return 0; 
    } 

    // initialize mutex and condition variable 
    pthread_mutex_init(&lock, NULL); 
    pthread_cond_init(&flag, NULL); 

    data.stop = 0; 
    data.flag = &flag; 
    data.lock = &lock; 
    data.failCount = 0; 
    data.successCount = 0; 

    for (i = 0; i < numThreads; ++i) { 
    if (!pthread_create(threads+i, NULL, foobar, 
     (void *)(threads+i))) { 
     // handle thread creation error 
    } 
    } 

    while (!data.stop) { 
    pthread_mutex_lock(&lock); 
    pthread_cond_wait(&cond, &lock); 
    // a thread just finished 
    if (data.failCount > 0) { 
     data.stop = 1; 
    } else if (data.successCount == numThreads) { 
     data.stop = 1; 
    } 
    pthread_mutex_unlock(&lock); 
    } 

    for (i = 0; i < numThreads; ++i) { 
    pthread_join(threads[i], NULL); 
    } 

    pthread_mutex_destroy(&lock); 
    pthread_cond_destroy(&flag); 
    free(threads); 
} 

它的工作方式是你等任何一個線程失敗,或所有線程成功,然後讓所有線程知道停止工作並通過stop變量乾淨地退出。

而不是讓線程檢查stop變量,你可以調用pthread_kill(),但它更好地乾淨地退出每個線程。

相關問題