1

我从https://pastebin.com/MM5kSvH6复制了以下线程池实现。一切看起来都不错,但我无法理解第 32 行和第 71 行的逻辑。这两行不是都在尝试执行该功能吗?我想在线程池中,线程应该从任务队列中提取任务然后执行它?从这个意义上说,第 71 行看起来不错,但我对第 32 行感到困惑。为什么不将任务添加到队列中,为什么要尝试执行相同的操作?

#include <condition_variable>
#include <functional>
#include <iostream>
#include <future>
#include <vector>
#include <thread>
#include <queue>
 
class ThreadPool
{
public:
    using Task = std::function<void()>;
 
    explicit ThreadPool(std::size_t numThreads)
    {
        start(numThreads);
    }
 
    ~ThreadPool()
    {
        stop();
    }
 
    template<class T>
    auto enqueue(T task)->std::future<decltype(task())>
    {
        auto wrapper = std::make_shared<std::packaged_task<decltype(task()) ()>>(std::move(task));
 
        {
            std::unique_lock<std::mutex> lock{mEventMutex};
            mTasks.emplace([=] {
                (*wrapper)();
            });
        }
 
        mEventVar.notify_one();
        return wrapper->get_future();
    }
 
private:
    std::vector<std::thread> mThreads;
 
    std::condition_variable mEventVar;
 
    std::mutex mEventMutex;
    bool mStopping = false;
 
    std::queue<Task> mTasks;
 
    void start(std::size_t numThreads)
    {
        for (auto i = 0u; i < numThreads; ++i)
        {
            mThreads.emplace_back([=] {
                while (true)
                {
                    Task task;
 
                    {
                        std::unique_lock<std::mutex> lock{mEventMutex};
 
                        mEventVar.wait(lock, [=] { return mStopping || !mTasks.empty(); });
 
                        if (mStopping && mTasks.empty())
                            break;
 
                        task = std::move(mTasks.front());
                        mTasks.pop();
                    }
 
                    task();
                }
            });
        }
    }
 
    void stop() noexcept
    {
        {
            std::unique_lock<std::mutex> lock{mEventMutex};
            mStopping = true;
        }
 
        mEventVar.notify_all();
 
        for (auto &thread : mThreads)
            thread.join();
    }
};
 
int main()
{
    {
        ThreadPool pool{36};
 
        for (auto i = 0; i < 36; ++i)
        {
            pool.enqueue([] {
                auto f = 1000000000;
                while (f > 1)
                    f /= 1.00000001;
            });
        }
    }
 
    return 0;
}
4

1 回答 1

1

第 32 行添加了一个 lambda,它在调用时执行任务,而第 71 行执行 lambda。一个简单地委托给另一个。简而言之,第 32 行只是 lambda 的一部分,它通过第 72 行的调用来执行。我们没有双重执行。相反,第 72 行是执行第 32 行所属的代码的行。

于 2021-07-29T08:49:12.027 回答