《C++ Concurrencyin
Action》讀書筆記
1、使用g++編譯多線程程序的時候需要加上-lpthread參數,如:
g++ -std=c++11–o run.out test.cpp –lpthread
2、多線程編程增加了頭文件#include<thread>,標準c++庫中對多線程支持的聲明在新的頭文件中,管理現成的函數和類在<thread>中聲明,而保護共享數據的函數和類在其他頭文件中聲明。每個線程都必須具有一個初始函數,新線程的執行在這裏開始,一般初始線程的main()函數,對於其他線程,可以在std::thread對象的構造函數中指定。
例子:
#include<iostream>
#include<thread>
using namespace std;
void thread_hello()
{
Cout <<“hello thread”<<endl;
}
Int main(void)
{
Threadt(thread_hello);
t.join();
//t.detach();
return 0;
}//end
Join:線程的加入,可以確保線程在函數完成前結束,能保證局部變量在縣城完成後才被銷燬;jion()只能對給定的對象調用一次,如果對給已加入的線程再次join()操作時,將會導致錯誤,可以調用joinable()進行判斷是否已經加入。
Detach:線程的分離,主調函數不等待線程結束。使用detach()會讓線程在後臺運行,意味着主線程不能與之直接交互。通常分離線程爲守護線程(沒有任何用戶接口,並在後臺運行的線程)。
3、在把函數對象傳入到線程構造函數中時,需要注意:如果傳遞了一個臨時變量(非命名的變量),c++編譯器會將其解析爲函數生命,而不是類型對象的定義,例如:
Std::threadmy_thread(test_thread());
這裏相當於聲明瞭一個帶有一個參數名爲my_thread並但會一個std::thread對象的函數。解決這個問題的四種方式:
1) 在前面命名函數對象;
2) 使用多組括號,std::thread my_thread((test_thread()));
3) 使用c++11新的初始化語法:std::thread my_thread{test_thread()};//大括號括起來;
4) 使用lambda表達式(允許使用一個可以捕獲局部變量的局部函數)。
4、爲了防止主調函數執行完成後(使用了detach),新線程還在運行(可能會訪問到已經銷燬的變量),常規方法:使線程函數的功能齊全,將數據複製到縣城中,而不是複製到共享數據中(引用和指針的不當使用)。
5、什麼情況下使用分離線程:一個程序執行多個相同的線程人物,每個線程運行相同的代碼,但是每個線程都是獨立的,完成與否對其他線程都不會產生影響。
6、向線程函數傳遞參數,例:
Void func(int i , std::string const&s);
Std::thread t(func, 3, “hello”);//注意字面值常量(char const *)向std::string對象的轉化
還可以傳遞一個成員函數指針作爲線程函數,並提供一個合適的對象指針作爲第一個參數。
7、不能通過賦一個新值給std::thread對象的方式來“丟棄”一個線程,std::thread支持移動,就意味着新線程的所有權可以在函數外進行轉移。例:
Std::thread f()
{
Void some_func();
Return std::thread(some_func);
/*或者如下定義:
*std::thread t(some_func);
*return t;*/
}
8、當所有權可以在函數內部傳遞,就允許std::thread實例可作爲參數進行傳遞。例:
Void f(std::threadt);
F(std::thread(some_function));
9、std::thread::hardware_concurrency(),該函數返回能同時併發在一個程序中的線程數量(多核系統中,返回值是cpu核心的數量)。
10、在確定了要使用的線程數量之後,通過創建一個std::vector<T>容器存放中間結果,併爲線程創建一個std::vector<std::thread>容器,需要注意:啓動線程的數量必須比num_threads小1,因爲在啓動之前已經有了一個主線程。
11、線程標識類型是std::thread::id,以兩種方式可以獲取:
1)通過調用std::thread對象的成員函數get_id()來直接過去,如果std::thread對象沒有與任何執行線程相關聯,get_id()將返回std::thread::type默認構造值,這個值表示沒有線程
2)當前線程中調用std::this_thread::get_id()(該函數也定義在<thread>頭文件中)。
Std::thread::id對象可以自由的拷貝和對比,因爲標識符就可以複用。如果兩個對象的std::thread::id相等,那它們就是同一個線程,或者都沒有線程。如果不等,那麼就代表了兩個不同線程,或者一個有線程一個沒有。