簡體   English   中英

C ++中隊列上的線程池

[英]Thread pool on a queue in C++

我一直在嘗試同時解決問題,這非常適合線程池模式。 在這里,我將嘗試提供一個最小的代表性示例:

假設我們有一個偽程序,如下所示:

Q : collection<int>
while (!Q.empty()) {
    for each q in Q {
        // perform some computation
    }
    // assign a new value to Q
    Q = something_completely_new();
}

我正在嘗試以n-1工作人員和一個主線程以並行方式實現這一點。 工作人員將通過從Q獲取元素在內部循環中執行計算。

我試圖使用兩個條件變量來解決這個問題,兩個是work變量,主線程在該變量上通知工作人員已經分配了Q,另一個工作work_done ,在工作work_done中通知工作人員整個計算可能已完成。

這是我的C ++代碼:

#include <iostream>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <thread>

using namespace std;

std::queue<int> Q;
std::mutex mut;
std::condition_variable work;
std::condition_variable work_done;

void run_thread() {
    for (;;) {
        std::unique_lock<std::mutex> lock(mut);
        work.wait(lock, [&] { return Q.size() > 0; });

        // there is work to be done - pretend we're working on something
        int x = Q.front(); Q.pop();
        std::cout << "Working on " << x << std::endl;

        work_done.notify_one();
    }
}

int main() {
    // your code goes here
    std::vector<std::thread *> workers(3);

    for (size_t i = 0; i < 3; i++) {
        workers[i] = new std::thread{
            [&] { run_thread(); }
        };
    }

    for (int i = 4; i > 0; --i) {
        std::unique_lock<std::mutex> lock(mut);
        Q = std::queue<int>();
        for (int k = 0; k < i; k++) {
            Q.push(k);
        }
        work.notify_all();
        work_done.wait(lock, [&] { return Q.size() == 0; });
    }

    for (size_t i = 0; i < 3; i++) {
        delete workers[i];
    }

    return 0;
}

不幸的是,在OS X上使用g++ -std=c++11 -Wall -o main main.cpp編譯后,得到以下輸出:

Working on 0
Working on 1
Working on 2
Working on 3
Working on 0
Working on 1
Working on 2
Working on 0
Working on 1
Working on 0
libc++abi.dylib: terminating
Abort trap: 6

經過一段時間的搜尋后,它看起來像是分割錯誤。 這可能與我濫用條件變量有關。 我希望能從結構上(關於如何解決此類問題)和特定的見識中獲得一些見識,就像我在這里做錯的那樣。

感謝您的幫助

您的應用程序被std::terminate殺死。

線程函數的主體是無限循環的,因此在執行這些行時

for (size_t i = 0; i < 3; i++) {
    delete workers[i];
}

您想要刪除仍在運行的線程(每個線程處於可連接狀態)。 當您調用處於可連接狀態的線程的析構函數時,會發生以下情況(來自http://www.cplusplus.com/reference/thread/thread/~thread/

如果線程在銷毀時是可連接的,則調用terminate()。

因此,如果您不希望terminate被調用,則應在創建線程后調用detach()方法。

  for (size_t i = 0; i < 3; i++) {
    workers[i] = new std::thread{
        [&] { run_thread(); }
    };
    workers[i]->detach();  // <---
}

僅僅因為隊列為空並不意味着工作已經完成。

finished = true;
work.notify_all();
for (size_t i = 0; i < 3; i++) {
    workers[i].join(); // wait for threads to finish
    delete workers[i];
}

我們需要某種方式來終止線程

for (;!finshed;) {
    std::unique_lock<std::mutex> lock(mut);
    work.wait(lock, [&] { return Q.size() > 0 || finished; });
    if (finished)
      return;

暫無
暫無

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

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