We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
start 成员函数:
start
void start(){ for (std::size_t i = 0; i < num_threads_; ++i){ pool_.emplace_back([this] { while (!stop_) { Task task; { std::unique_lock<std::mutex> lc{ mutex_ }; if (tasks_.empty()) return; cv_.wait(lc, [this] {return stop_ || !tasks_.empty(); }); task = std::move(tasks_.front()); tasks_.pop(); } task(); } }); } }
问题在于:
std::unique_lock<std::mutex> lc{ mutex_ }; if (tasks_.empty()) return;
这样写可能导致线程开始执行,任务还没加入,队列为空,就直接退出了。
ThreadPool pool{ 4 }; // 构造函数调用 start 成员函数,任务还未加入,直接退出 // ... pool.submit(task); // 任务还未加入
有时你可以看到任务正确执行,有时不行。这个问题的原因很简单: pool_.emplace_back 只是构造线程对象,线程对象构造代表启动线程,但是线程何时执行,是系统调度的事情,也和硬件有所关系。
pool_.emplace_back
正常的做法我们应该是将判断移动到 cv_.wait 的下面,也就是:
cv_.wait
std::unique_lock<std::mutex> lc{ mutex_ }; cv_.wait(lc, [this] {return stop_ || !tasks_.empty(); }); if (tasks_.empty()) return;
join() 成员函数:
join()
void join(){ for (auto& thread : pool_) { if (thread.joinable()) { thread.join(); } } pool_.clear(); }
但是一旦改成这样,我们的 join() 成员函数则可能出现阻塞,这是因为:
假设线程池有三个线程,添加了 2 个任务给线程池执行,线程 1 2 去执行完毕了,任务队列也就空了。
然而线程 3 在调用 wait 函数的时候被阻塞了。
wait
cv_.wait(lc, [this] {return stop_ || !tasks_.empty(); });
我们调用 join() 成员函数,另外两个线程正常的退出,但是线程 3 会被一直阻塞在 wait 无法退出,因为条件始终无法满足,stop_ 只有在调用 stop() 成员函数后才会为 true,而 !tasks_.empty() 因为线程队列已经为空,所以始终为 false,将一直阻塞。
stop_
stop()
true
!tasks_.empty()
false
放弃 join() 成员函数并修改给出的使用示例,
The text was updated successfully, but these errors were encountered:
修改完善线程池的内容 #12
0b7e481
1. fix 线程池的实现中存在错误 #24 2. 修改示例的打印输出,增加线程 id
No branches or pull requests
start
成员函数:问题在于:
这样写可能导致线程开始执行,任务还没加入,队列为空,就直接退出了。
有时你可以看到任务正确执行,有时不行。这个问题的原因很简单:
pool_.emplace_back
只是构造线程对象,线程对象构造代表启动线程,但是线程何时执行,是系统调度的事情,也和硬件有所关系。正常的做法我们应该是将判断移动到
cv_.wait
的下面,也就是:join()
成员函数:但是一旦改成这样,我们的 join() 成员函数则可能出现阻塞,这是因为:
假设线程池有三个线程,添加了 2 个任务给线程池执行,线程 1 2 去执行完毕了,任务队列也就空了。
然而线程 3 在调用
wait
函数的时候被阻塞了。我们调用
join()
成员函数,另外两个线程正常的退出,但是线程 3 会被一直阻塞在wait
无法退出,因为条件始终无法满足,stop_
只有在调用stop()
成员函数后才会为true
,而!tasks_.empty()
因为线程队列已经为空,所以始终为false
,将一直阻塞。修改
放弃
join()
成员函数并修改给出的使用示例,The text was updated successfully, but these errors were encountered: