簡體   English   中英

在C ++中使用pthreads實現線程池

[英]Pool of threads implementation using pthreads in C++

我在設計一個包含線程池的程序時遇到了麻煩。

我堅持的主要問題是當一個線程完成工作時,父必須在threadId上等待(這是父進程使用pthread_join等待線程)。 因為我們不知道哪個線程將首先完成,所以我無法找到解決問題的程序方法。

任何解釋與一小段代碼表示贊賞。

謝謝。

好吧,我不知道你的設置或要求,但你遇到了pthread_join()正好等待一個線程的問題,你實際上想要等待任何線程。

因此,最明顯的結論是pthread_join對你沒有幫助。 很抱歉說明顯了,但我需要建立我的案例:-)

相反,你可能不得不提出另一個想法。 例如,您可以等待條件變量; 在線程退出之前將條件設置為“退出”。 主線程可以等待該條件,遍歷線程以找出哪些已終止(可能多於一個),並最終重置條件。 條件互斥通常足以防止比賽。

除了設置條件之外,線程還可以將一些ID添加到退出線程列表中(您可以使用條件互斥鎖來保護該列表),因此主線程只需要遍歷該列表而不是檢查每個線程。

偽代碼:

initialize condition variable with status "not exited"
...
...
launch your threads
...
...
while (some threads are still running) do
   lock condition variable on "exited"
   iterate through threads, remove the ones that have exited
   unlock condition variable with new condition "not exited"

在你的線程內:

 ...
 do whatever it needs to do
 ...
 ...
 lock condition variable
 unlock condition variable with new condition "exited"
 /* end of thread */

池通常實現為在生產者 - 消費者隊列上等待任務項的多個線程。 任務是從具有'run()'方法的Task類派生的對象。 無論哪個線程獲得任務,它都會調用run(),並且當返回時,線程循環以從隊列中獲取另一個任務對象。

這吹走了任何線程微管理,並且可靠,安全地工作在我嘗試過的每一個系統/語言上。

我知道完成通知的最靈活方式是線程在run()返回時調用'OnComplete'事件,或者可能是虛擬的'completed'方法,就在循環返回以獲取下一個任務之前,任務作為參數。 例如,此方法/事件可以發出任務源線程正在等待的事件/ condvar / sema的信號,可以將完成的任務排隊到原始線程或另一個線程,甚至只刪除()任務,(也許是作業完全在線程池中完成)。

對於錯誤通知,我捕獲run()拋出的任何未捕獲的異常,並在調用完成方法/事件之前將異常存儲在tast字段中。

除了那些保護生產者 - 消費者隊列的鎖之外沒有鎖(並且它們只需要足夠長的時間來推送/彈出*任務)。

無論您使用哪種設計,請盡量不要:

1) continually create/terminate/destroy threads - avoidable overhead and tricky to manage
2) wait with Join() for any thread to terminate - just don't :)
3) loop around some 'poll thread status' to see if they're finished yet - gets it wrong
4) Move 'working/finished' threads into and out of containers with complicated locks - deadlock-in-the-making
5) use any other sort of micro-management - difficult, messy, error-prone, too many locks, unnecesary, avoidable

理想的線程池是你不知道哪個線程工作的地方。 實際上,通常甚至不需要保留對線程的任何引用。 雙線偽threadPool:

TblockingQueue *inQueue=new TblockingQueue();
for(int i=0;i<CpoolDepth,i++) new Thread(inQueue);

如果您正在嘗試實現線程池,請查看我幾年前玩過的這種架構。 我在這里寫了它: C ++中的線程池

對於非阻塞pthread_join,請參閱此SO討論: 非阻塞pthread_join

如果你只是等待所有線程完成他們的工作,你可以一個接一個地等待它們:順序無關緊要,並且沒有理由使用條件。 此示例演示:

#include <memory.h>
#include <pthread.h>

#include <iostream>

using namespace std;

#define NTHREADS 10

void *thread(void *arg) {
    int *n = (int *) arg;
    sleep(10 - *n);
    cout << "Thread " << (*n) << endl;
    delete n;
    return NULL;
}

int main(int argc, char **argv) {
    pthread_t threads[NTHREADS];
    pthread_attr_t attr;
    memset(&attr, 0, sizeof(attr));
    int i;
    for (i=0; i<NTHREADS; i++) {
        int *p = new int;
        *p = i;
        pthread_create(threads + i, &attr, thread, p);
    }
    void *rval;
    for (i=0; i<NTHREADS; i++) {
        pthread_join(threads[i], &rval);
        cout << "Joined thread " << i << endl;
    }
    return 0;
}

雖然線程的順序以與等待相反的順序完成(即線程0最后完成,但我們先在線程0上等待),但主線程將不會退出,直到所有線程都完成。 無需條件。


暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM