使用lambda表达式构造线程

时间:2015-06-20 00:30:46

标签: multithreading c++11 lambda threadpool

有人可以解释下面lambda函数创建线程的位置吗? 使用的技术是什么? 有人可以推荐一个参考来理解语义吗?

我现在发布了完整的代码:

class ThreadPool {
public:
    ThreadPool(size_t);
    template<class F, class... Args>
    auto enqueue(F&& f, Args&&... args)
        ->std::future<typename std::result_of<F(Args...)>::type>;
    ~ThreadPool();
private:
    // need to keep track of threads so we can join them
    std::vector< std::thread > workers_m;
    // the task queue
    std::queue< std::function<void()> > tasks_m;

    // synchronization
    std::mutex queue_mutex_m;
    std::condition_variable condition_m;
    bool stop_m;
};

// the constructor just launches some amount of workers
inline ThreadPool::ThreadPool(size_t threads)
    : stop_m(false)
{
    std::thread::id id = std::this_thread::get_id();
    for (size_t i = 0; i < threads; ++i)
    {
        workers_m.emplace_back(
            [this]
        {
            for (;;)
            {
                std::function<void()> task;
                {
                    std::unique_lock<std::mutex> lock(this-    >queue_mutex_m);
                    std::thread::id id1 = std::this_thread::get_id();
                    this->condition_m.wait(lock, [this]{ return this->stop_m || !this->tasks_m.empty(); });
                    std::thread::id id = std::this_thread::get_id();
                    if (this->stop_m && this->tasks_m.empty())
                        return;
                    task = std::move(this->tasks_m.front());
                    this->tasks_m.pop();
                }
                task();
            }
        }
        );
    }
}

1 个答案:

答案 0 :(得分:0)

ThreadPool的构造函数正在使用emplace_back的{​​{1}}函数在std::vector变量的后面构造std::threadworkers_memplace_back的不同之处在于它通过转发传递给元素类型(push_back)的构造函数的参数来直接构造元素类型。另一方面,std::thread需要左值或临时元素类型,然后将适当地复制或移动到向量的后面。

push_back的构造函数将在for循环中执行此操作,以创建适当数量的工作线程,由构造函数参数(ThreadPool)指定。 std::threads constructors中的一个获取可调用的和任意数量的参数,并将在相应的线程上运行该函数。在这种情况下,传入的lambda用于构造一个线程,该线程将根据需要运行(由threads给出),获取互斥锁以授予对任务队列的独占访问权限,并使用条件变量等待,直到设置了停止标志,或者直到队列中有可用的东西为止。

一旦通知条件变量并且两个条件之一为真,则线程可以继续。但是,这两个条件中的哪一个是真实的是未知的,因此检查

for(;;)

虽然看起来有点缺陷,因为如果设置了if (this->stop_m && this->tasks_m.empty()) return; ,工作线程应该停止处理任务,即使队列仍然包含要执行的任务。但这种检查只会触发两种情况都属实。

如果上述检查为false,则线程stop_m执行队列之外的任务std::move,然后释放由pop()保留的互斥锁。由于锁的析构函数。然后线程通过调用它来执行任务。由于unique_lock循环

,然后重复此过程