在书里
您可以找到以下两个代码段(我进行了一些细微的修改):
片段1:
class thread_guard
{
std::thread& t;
public:
explicit thread_guard(std::thread& t_): t(t_){}
~thread_guard()
{
if(t.joinable())
{
t.join();
}
}
thread_guard(thread_guard const&)=delete;
thread_guard& operator=(thread_guard const&)=delete;
};
void my_func()
{
for(int j = 0; j < 1000; ++j)
{
cout << "\n " << j;
}
}
void f()
{
std::thread t1(my_func);
thread_guard g(t1);
do_something_in_current_thread();
}
int main()
{
f();
return 0;
}
继续你可以找到
片段2:
class scoped_thread
{
std::thread t;
public:
explicit scoped_thread(std::thread t_): t(std::move(t_))
{
if(!t.joinable())
throw std::logic_error(“No thread”);
}
~scoped_thread()
{
t.join();
}
scoped_thread(scoped_thread const&)=delete;
scoped_thread& operator=(scoped_thread const&)=delete;
};
void my_func()
{
for(int j = 0; j < 1000; ++j)
{
cout << "\n " << j;
}
}
void f()
{
scoped_thread st1(thread(my_func));
thread t2(my_func);
scoped_thread st2(move(t2));
do_something_in_current_thread();
}
int main()
{
f();
return 0;
}
我不确定我是否真的能体会到这两个摘要之间的真正区别。
我可以看到的唯一区别是,在代码片段1中,
thread_guard
实例不拥有线程t1
的所有权(与scoped_thread
对象不同),因此可以调用t1.join()
,但这在执行~thread_guard()
时不成问题。那么:摘录2的优势在哪里(如果存在)?
最佳答案
这两种类型都将在破坏(例如作用域退出)时阻塞,直到线程完成为止。不同之处在于thread
对象的所有权。thread_guard
本身不拥有thread
;在同一个thread_guard
上可能有不止一个thread
在等待。这也意味着,只要任何thread
引用了thread_guard
对象,该对象都必须处于 Activity 状态。如果销毁了thread_guard
对象时已引用的线程已经加入,则不会阻塞或产生错误(与仅在不可连接的线程上调用join
相对)。
另一方面,scoped_thread
拥有thread
实例的所有权,因此也控制了它的生存期。每当您想拥有自己要等待的线程时,例如,当您拥有该线程时,就可以使用它。作为数据成员。
最终,您使用的是一个语义问题:您要等待别人拥有的线程(然后还必须确保不存在生命周期问题),还是想要thread
对象在获取时阻塞?已销毁,无需先对其进行join
编码。
关于c++ - thread_guard与scoped_thread,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56497350/