2008-09-16 331 views
20

我正在編寫一個多線程服務器的關閉。如果一切順利,所有的線程都會自行退出,但線程卡住的可能性很小。在這種情況下,它會很方便有一個非阻塞連接,所以我可以做。非阻塞pthread_join

有沒有辦法做一個非阻塞pthread_join? 某種定時加入也不錯。

是這樣的:

 
foreach thread do 
    nb_pthread_join(); 
    if still running 
     pthread_cancel(); 

我能想到的更多的情況下,一個非bloking加入將是有益的。

由於看起來沒有這樣的功能,所以我已經編碼了一個解決方法,但它並不像我想的那麼簡單。

+1

非阻塞線程連接?我認爲加盟是所有關於阻止:s – 2008-09-16 15:22:04

回答

1

正如其他人指出的那樣,標準pthread庫中沒有可用的非阻塞pthread_join。

但是,考慮到你陳述的問題(試圖保證你的所有線程退出程序關閉),這樣的功能是不需要的。你可以簡單地這樣做:

int killed_threads = 0; 
for(i = 0; i < num_threads; i++) { 
    int return = pthread_cancel(threads[i]); 
    if(return != ESRCH) 
     killed_threads++; 
} 
if(killed_threads) 
    printf("%d threads did not shutdown properly\n", killed_threads) 
else 
    printf("All threads exited successfully"); 

沒有什麼錯,呼籲所有線程pthread_cancel可以(終止或不),因此呼籲對所有的線程不會阻止,並保證線程退出(乾淨與否)。

這應該符合'簡單'的解決方法。

+22

這個答案是錯誤的。在每個線程上成功調用`pthread_cancel`並不能保證所有線程都退出。他們可能沒有達到任何取消點,或者即使他們有,主線程可能會首先安排並從`main`返回,在其他線程完成清理之前終止進程... – 2011-07-07 03:32:35

0

您可以將一個字節插入一個打開爲非阻塞的管道,以便在完成時向另一個線程發送信號,然後使用非阻塞讀取來檢查管道的狀態。

1

答案真的取決於你爲什麼要這樣做。例如,如果你只是想清理死線程,那麼最簡單的方法就是擁有一個循環和連接的「死線程清理器」線程。

1

我不確定你的意思,但我假設你真正需要的是一個等待和通知機制。

總之,它是如何工作的:你等待一個條件滿足超時。你的等待將超過如果:

  • 發生超時,或
  • 如果條件得到滿足。

你可以在一個循環中添加更多的智能邏輯。我發現的與Pthreads相關的最佳資源是本教程: POSIX線程編程(https://computing.llnl.gov/tutorials/pthreads/)。

我也很驚訝地發現Pthreads中沒有定時連接的API。

1

沒有定時pthread_join,但如果你正在等待阻塞條件的其他線程,你可以使用定時pthread_cond_timed_wait,而不是pthread_cond_wait

2

如果你對QNX開發時,可以使用pthread_timedjoin()函數。

否則,您可以創建一個單獨的線程來執行pthread_join(),並通過發信號通知子線程完成,從而提醒父線程。這個單獨的線程可以返回從pthread_join()獲取的內容,以便讓父線程不僅確定何時完成子進程,還要確定它返回的值。

21

如果您運行的Linux上的應用程序,你可能有興趣知道:

int pthread_tryjoin_np(pthread_t thread, void **retval); 

int pthread_timedjoin_np(pthread_t thread, void **retval, 
           const struct timespec *abstime); 

要小心,因爲後綴表明它,「NP」是指「非便攜式」。它們不是POSIX標準的gnu擴展,雖然有用。

link to man page

9

的「在pthread_join」機制是如果碰巧做的正是你想要的要使用的便利性。它不會做任何你無法做到的事情,也不會做你想要的東西,而只是編寫你想要的東西。

沒有真正的理由,你應該真正關心一個線程是否已經終止。你關心的是線程正在完成的工作是否完成。爲了說明,讓線程做一些事情來表明它正在工作。你如何做到這一點取決於什麼是你的具體問題的理想,這很大程度上取決於線程正在做什麼。

從改變你的想法開始。這不是一個被卡住的線程,而是線程正在做的事情被卡住。

+0

請添加示例代碼?我有同樣的問題,一個進程調用兩個線程,並且應該只在線程退出時退出 - 這裏的任何響應都沒有解釋如何執行類似於fork的wait()函數的類似方法。 (我將這個問題添加到收藏夾,一旦你自動回覆,它會通知我) – 2012-01-10 23:37:36