1 線程啟動(dòng)
2 參數(shù)傳遞
2.1 參數(shù)傳遞
2.2 引用傳參
3 線程所有權(quán)管理
4 線程標(biāo)志
1 線程啟動(dòng)
std::thread構(gòu)造函數(shù)接受可調(diào)用對(duì)象啟動(dòng)線程壹店,如下所示:
#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();
}
假設(shè)文件名為thread.cpp, 則編譯命令為:
g++ -std=c++11 -lpthread thread.cpp -o test_thread
執(zhí)行./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 參數(shù)傳遞
2.1 基本范例
下面例子是一個(gè)向線程傳遞參數(shù)的示例
#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();
}
這個(gè)程序存在一個(gè)隱患, 由于主進(jìn)程detach了师坎,所以buffer在轉(zhuǎn)成std::string之前有可能因?yàn)橹鬟M(jìn)程退出而銷毀耍攘,正確的方式是在主進(jìn)程中就把buffer轉(zhuǎn)成std::string, 如下
// std::thread t(f, 3, buffer); =>
std::thread t(f, 3, std::string(buffer));
2.2 引用傳參
C++11 支持使用std::ref向線程按照引用方式傳遞參數(shù), 如下范例:
#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;
}
程序輸出結(jié)果為:
i=1
s=update value
3 線程所有權(quán)管理
std::thread都是可移動(dòng)榕栏,但不可拷貝, 如下面示例:
#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
對(duì)于需要join的線程蕾各,為了確保join一定會(huì)被調(diào)用扒磁,可以創(chuàng)建下面的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中式曲,批量創(chuàng)建線程并且等待它們結(jié)束妨托,示例如下:
#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 線程標(biāo)志
線程標(biāo)識(shí)類型是std::thread::id,可以通過(guò)兩種方式進(jìn)行檢索吝羞。第一種兰伤,可以通過(guò)調(diào)用std::thread對(duì)象的成員函數(shù)get_id()來(lái)直接獲取。如果std::thread對(duì)象沒有與任何執(zhí)行線程相關(guān)聯(lián)钧排,get_id()將返回std::thread::type默認(rèn)構(gòu)造值敦腔,這個(gè)值表示“沒有線程”。第二種恨溜,當(dāng)前線程中調(diào)用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