线程不同于普通的local variable.即使一个跑在函数中的线程,如果该函数由于if-elseif, return或者其他原因而提前结束了那么该函数内的变量遵循RAII原则,自动销毁,然而线程则不会,仍然就继续执行下去。
我们来首先看一个例子:
#include <iostream>
#include <thread>
#include <vector>
constexpr unsigned long tenMillion = 10000000;
bool doWork(std::function<bool(const int&)> filter, const unsigned long& maxVal = tenMillion)
{
std::vector<int> vec;
std::function<bool()> conditionsAreSatisfied = [&vec]()->bool { return false; };
std::thread t([&filter, maxVal, &vec]() { for (unsigned long i = 0; i <= maxVal; ++i) { if (filter(i)) vec.push_back(i); }});
if (conditonsAreSatisfied()) { //注意前面我们设置了conditionsAreSatisfied()返回false.
thread.get().join();
return true;
}else { //由于返回的是false,因此该线程并没有被join()也没有被detach().
return false;
}
}
int main()
{
doWork([](const int& number)->bool { return (number % 2 == 0) ? true : false;});
return 0;
}
有时候我们可能在一个函数里面可能会用if-elseif产生很多分支每种分支对应的情况也不一样。
这就造成了我们可能没有对当前函数的的std::thread执行join(),然后就结束了函数的生命周期(lifetime),这么一来我们跑在该函数的线程如果是以引用的形式使用了当前函数内的local variable,很显然就会造成terminal咯.
肯定是有解决办法的我们再来看一个例子:
#include <iostream>
#include <thread>
#include <vector>
class ThreadRAII {
public:
enum class Action : int {join, detach};
ThreadRAII(std::thread&& t, ThreadRAII::Action act);
~ThreadRAII();
std::thread& get();
private:
Action action;
std::thread thread;
};
ThreadRAII::ThreadRAII(std::thread&& t, ThreadRAII::Action act)
:thread(std::move(t)),
action(act)
{
//
}
std::thread& ThreadRAII::get()
{
return (this->thread);
}
ThreadRAII::~ThreadRAII()
{
if (thread.joinable()) {
if (this->action == Action::join) {
(this->thread).join();
}else{
(this->thread).detach();
}
}
}
constexpr unsigned long tenMillion = 10000000;
bool doWork(std::function<bool(const int&)> filter, const unsigned long& maxVal = tenMillion)
{
std::vector<int> vec;
std::function<bool()> conditionsAreSatisfied = [&vec]()->bool { return false; };
//std::thread t([&filter, maxVal, &vec]() { for (unsigned long i = 0; i <= maxVal; ++i) { if (filter(i)) vec.push_back(i); }});
ThreadRAII thread(std::thread([&filter, maxVal, &vec]() { for (unsigned long i = 0; i <= maxVal; ++i) { if (filter(i)) vec.push_back(i); }}), ThreadRAII::Action::join);
if (false) { //注意这里的false.
thread.get().join();
return true;
}else { //在return之前ThreadRAII的析构函数被调用,这样即使前面没有对thread进行jion(),在ThreadRAII的析 //构函数里面也会调用jion()的
return false;
}
}
int main()
{
doWork([](const int& number)->bool { return (number % 2 == 0) ? true : false;});
return 0;
}