1 线程启动
2 参数传递
2.1 参数传递
2.2 引用传参
3 线程所有权管理
4 线程标志
1 线程启动
std::thread构造函数接受可调用对象启动线程,如下所示:
#include <iostream>
#include <thread>
#include <string>
#include <functional>
void f(int i) {
std::cout << "Func, i=" << i << "\n";
}
struct Foo {
void operator()(int i) {
std::cout << "Class Function Call Object, i=" << i << "\n";
}
};
struct Foo2 {
void func(int i) {
std::cout << "Class Method, i=" << i << "\n";
}
};
int main() {
// by normal function
std::thread t1(f, 1);
t1.join();
// by class operator()
Foo foo;
std::thread t2(foo, 2);
t2.join();
//by lamda
int i = 3;
std::thread t3([i]() {
std::cout << "Lamda, i=" << i << "\n";
});
t3.join();
// by member function
Foo2 foo2;
auto f3 = std::mem_fn(&Foo2::func);
std::thread t4(f3, foo2, 4);
t4.join();
// by bind
auto f1 = std::bind(f, std::placeholders::_1);
std::thread t5(f1, 5);
t5.join();
// by std::function
std::function<void(int)> f2 = f;
std::thread t6(f2, 6);
t6.join();
}
假设文件名为thread.cpp, 则编译命令为:
g++ -std=c++11 -lpthread thread.cpp -o test_thread
执行./test_thread后程序输出为
Func, i=1
Class Function Call Object, i=2
Lamda, i=3
Class Method, i=4
Func, i=5
Func, i=6
2 参数传递
2.1 基本范例
下面例子是一个向线程传递参数的示例
#include <iostream>
#include <thread>
#include <string>
void f(int i, const std::string& s) {
std::cout << "i = " << i << "\n"
<< "s = " << s << std::endl;
}
int main() {
char buffer[1024];
sprintf(buffer, "%i", 1234);
std::thread t(f, 3, buffer);
t.detach();
}
这个程序存在一个隐患, 由于主进程detach了,所以buffer在转成std::string之前有可能因为主进程退出而销毁,正确的方式是在主进程中就把buffer转成std::string, 如下
// std::thread t(f, 3, buffer); =>
std::thread t(f, 3, std::string(buffer));
2.2 引用传参
C++11 支持使用std::ref向线程按照引用方式传递参数, 如下范例:
#include <iostream>
#include <thread>
#include <string>
void func(int& i, std::string& s) {
++i;
s = "update value";
}
int main() {
int i = 0;
std::string s("old value");
std::thread t(func, std::ref(i), std::ref(s));
t.join();
std::cout << "i=" << i << "\n"
<< "s=" << s << std::endl;
return 0;
}
程序输出结果为:
i=1
s=update value
3 线程所有权管理
std::thread都是可移动,但不可拷贝, 如下面示例:
#include <iostream>
#include <thread>
void f(int i) {
std::cout << "Func, i=" << i << "\n";
}
std::thread gen_a_thread() {
std::thread t(f, 2);
return t;
}
int main() {
std::thread t1(f, 1);
//std::thread t2 = t1; this is not allowed
// transfer ownership, call move constructor
std::thread t2 = std::move(t1);
t2.join();
// transfer ownership, call move constructor
std::thread t3 = gen_a_thread();
t3.join();
}
输出为:
Func, i=1
Func, i=2
对于需要join的线程,为了确保join一定会被调用,可以创建下面的thread_scope类,如下:
#include <iostream>
#include <thread>
#include <exception>
void f(int i) {
std::cout << "Func, i=" << i << "\n";
}
class ThreadScope {
public:
explicit ThreadScope(std::thread t): _t(std::move(t)) {
if (!_t.joinable()) {
throw std::logic_error("no thread");
}
}
~ThreadScope() {
_t.join();
}
//disallow copy and assign
ThreadScope(const ThreadScope& t) = delete;
ThreadScope& operator=(const ThreadScope& t) = delete;
private:
std::thread _t;
};
int main() {
ThreadScope ts(std::thread(f, 1));
}
可以将std::thread放入std::vector中,批量创建线程并且等待它们结束,示例如下:
#include <iostream>
#include <thread>
#include <vector>
#include <sstream>
#include <algorithm>
void worker(int i) {
std::stringstream ss;
ss << "worker_";
ss << i;
ss << "\n";
std::cout << ss.str();
}
int main() {
const size_t WORKER_NUM = 20;
std::vector<std::thread> threads;
for (auto i = 0; i < WORKER_NUM; ++i) {
threads.emplace_back(std::thread(worker, i));
}
std::for_each(threads.begin(), threads.end(), std::mem_fn(&std::thread::join));
}
4 线程标志
线程标识类型是std::thread::id,可以通过两种方式进行检索。第一种,可以通过调用std::thread对象的成员函数get_id()来直接获取。如果std::thread对象没有与任何执行线程相关联,get_id()将返回std::thread::type默认构造值,这个值表示“没有线程”。第二种,当前线程中调用std::this_thread::get_id()。 示例代码如下:
#include <iostream>
#include <thread>
#include <vector>
#include <sstream>
#include <algorithm>
void worker(int i) {
std::stringstream ss;
ss << std::this_thread::get_id() << "\n";
std::cout << ss.str();
}
int main() {
const size_t WORKER_NUM = 5;
std::vector<std::thread> threads;
for (auto i = 0; i < WORKER_NUM; ++i) {
threads.emplace_back(std::thread(worker, i));
}
std::for_each(threads.begin(), threads.end(), std::mem_fn(&std::thread::join));
}
输出如下:
139865582319360
139865571829504
139865561339648
139865540359936
139865550849792
网友评论