线程管理——转移线程所有权

前言

 
在上一节中我们已经提及std::thread对象是一个move only object,而move的过程也正是转移线程所有权的过程。本节将对如何转移线程所有权,以及转移线程所有权的实际应用场景作出简单介绍。


转移实例

赋值

下述实例创建了两个执行线程,并且展示了如何在std::thread实例(t1,t2和t3)之间转移所有权:

1
2
3
4
5
6
7
8
void some_function(); 
void some_other_function();
std::thread t1(some_function);
std::thread t2=std::move(t1);
t1=std::thread(some_other_function);// 临时对象隐式触发了移动
std::thread t3;
t3=std::move(t2);
t1=std::move(t3); // 崩溃

值得注意的是最后一个移动操作,该操作试图将t3拥有的执行线程转交t1,但由于t1已拥有执行线程,因此系统将调用terminate(),强行终止程序运行。之前我们已经提过,需要在std::thread对象析构前显式地joindetach,赋值操作亦是如此,不存在通过赋值来“丢弃”某个运行线程的概念。

函数外传递

类似地,线程所有权也可以在函数外传递,例如将std::thread对象作为返回值:

1
2
3
4
5
6
7
8
9
std::thread f() {
void some_function();
return std::thread(some_function);
}
std::thread g() {
void some_other_function(int);
std::thread t(some_other_function,42);
return t;
}

std::thread也可以作为形参:
1
2
3
4
5
6
7
void f(std::thread t); 
void g() {
void some_function();
f(std::thread(some_function));
std::thread t(some_function);
f(std::move(t));
}


应用场景

RAII

为了保证线程总能被等待,我们可以创建RAII对象scoped_thread,该对象持有一个std::thread,和之前所提及的thread_guard不同的是,这里将在构造函数中作出检查,如果某个线程不可加入,则抛出异常:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;
};

struct func;

void f() {
int some_local_state;
scoped_thread t(std::thread(func(some_local_state)));
do_something_in_current_thread();
}

在f函数结束时,scoped_thread析构函数触发,执行对线程的等待。

自动化管理

std::thread也可以被装入容器(如果容器是移动敏感的),这意味着我们可以批量生产一些线程:

1
2
3
4
5
6
7
8
void do_work(unsigned id);
void f() {
std::vector<std::thread> threads;
for(unsigned i=0; i < 20; ++i) {
threads.push_back(std::thread(do_work,i));
}
std::for_each(threads.begin(),threads.end(),std::mem_fn(&std::thread::join));
}

std::thread置入std::vector是迈向线程自动化管理的第一步,这一行为揭示了在实际应用中我们无需为每一个std::thread创建独立的对象,可以通过批量操作的形式完成构造与加入(join)。