原 总结 C++11 thread 
缘起
从C++11开始提供了线程的支持,终于可以方便的编写跨平台的线程代码了。除了std::thread类,还提供了许多其它便利同步的机制,本篇总结是C++11学习笔记系列的首篇总结。
std::thread
std::thread定义在<thread>中,提供了方便的创建线程的功能。
类定义
- class thread 
 - { 
 - public: 
 -     thread() noexcept; 
 -     thread( thread&& other ) noexcept; 
 -     template< class Function, class... Args > 
 -     explicit thread( Function&& f, Args&&... args ); 
 -     thread(const thread&) = delete; 
 -     ~thread(); 
 -     thread& operator=( thread&& other ) noexcept; 
 -     bool joinable() const noexcept; 
 -     std::thread::id get_id() const noexcept; 
 -     native_handle_type native_handle(); 
 -     void join(); 
 -     void detach(); 
 -     void swap( thread& other ) noexcept; 
 -     static unsigned int hardware_concurrency() noexcept; 
 - }; 
 
 
从定义中我们可以得知:
各个成员函数的简单介绍
例子
因为thread类比较简单,我们通过几个例子来学习。
- #include <thread> 
 - void some_function() {} 
 - void some_other_function() {} 
 - int main() 
 - { 
 -     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); 
 - } 
 
 
- #include <iostream> 
 - #include <thread> 
 - #include <chrono> 
 -   
 - void foo() { 
 -     std::this_thread::sleep_for(std::chrono::seconds(1)); 
 - } 
 -   
 - int main() { 
 -     std::cout << "starting first helper...\n"; 
 -     std::thread helper1(foo); 
 -     helper1.join(); 
 - } 
 
 
- void f(int i, std::string const& s); 
 - std::thread t(f, 3 "hello"); 
 
 
注意:参数会以默认的方式被复制到内部存储空间,直到使用的时候才会转成对应的类型。
下面的例子有问题吗?有什么问题?
- void f(int i, std::string const& s); 
 - void oops(int some_param) 
 - { 
 -     char buffer[1024]; 
 -     sprintf(buffer, "%i", some_param); 
 -     std::thread t(f, 3, buffer); 
 -     t.detach(); 
 - } 
 
 
局部变量buffer的指针会被传递给新线程,如果oops()在buffer被转换成string之前退出,那么会导致未定义的行为。解决之道是在构造std::thread的时候传递string变量。std::thread t(f, 3, std::string(buffer));
因为默认会复制,如果像要传递引用,需要使用std::ref()来标识,就像std::bind()那样。
- std::thread t(update_data_for_widget, w, std::ref(data)); 
 
 
- #include <thread> 
 - #include <string> 
 - class CRunner 
 - { 
 - public: 
 -     void run0(){} 
 -     void run1(int a) {} 
 -     void run2(int a, int b) {} 
 -     int  run3(int a, char b, const std::string& c) {return 0;} 
 -     int  run4(int& a, double b, float c, char d) { ++a; return 0; } 
 -     static void run_static(int a) {} 
 - }; 
 -  
 - int main() 
 - { 
 -     CRunner runner; 
 -     int a = 0; 
 -      
 -     std::thread t0(std::mem_fun(&CRunner::run0), &runner); 
 -       
 -     std::thread t1(std::mem_fun_ref(&CRunner::run1), std::ref(runner), 1); 
 -      
 -     std::thread t2(std::mem_fn(&CRunner::run2), std::ref(runner), 1, 2); 
 -      
 -     std::thread t3(std::bind(std::mem_fn(&CRunner::run3), &runner, 1, 2, "data"));  
 -      
 -     std::thread t4(std::mem_fn(&CRunner::run4), &runner, std::ref(a), 2.2, 3.3f, ‘d‘);  
 -      
 -     std::thread t5(&CRunner::run_static, 1); 
 -  
 -     t0.join(); 
 -     t1.join(); 
 -     t2.join(); 
 -     t3.join(); 
 -     t4.join(); 
 -     t5.join(); 
 - } 
 
 
参考资料