C++並發編程學習筆記<2> 線程管理,學習筆記線程
線程管理
基本線程管理
啟動一個線程
<1>最簡單的一種類型
void do_some_work();std::thread my_thread(do_some_work);
<2>函數對象的形式
#include<iostream>#include<thread>using namespace std;class Say_hello{public: void operator()(){cout<<"hello";}};int main(){ Say_hello hello; std::thread t(hello); t.join(); return 0;}
一旦開啟一個線程,你需要明確地決定是否要等它結束 (通過join()函數 ),或讓它自己後台運行(通過detach函數)
如果你不在std :: thread對象被銷毀之前決定, 那麼程式會被終止。如果你不想等待線程結束,也要保證在該線程結
束之前,它訪問的資料都是有效。
等待線程完成
thread_name.join();
thread_name.detach();
前面說了要在對象銷毀之前確定是否等待線程結束。如果調用detach()函數,一般在開啟線程之後馬上調用,不會
出什麼問題。但如果你要調用join()函數,應該小心選取調用該函數的位置。因為如果線上程開啟之後,join()
函數調用之前拋出了異常,可能會跳過join()函數,導致出錯。
一種解決方案:
class thread_guard{ std::thread& t;public: explicit thread_guard(std::thread& t_):t(t_){}; ~thread_guard() { if(t.joinable()) { t.join(); } } thread_guard(thread_guard const&)=delete; thread_guard& operator=(thread_guard const&)=delete;};void f(){ std::thread t(hello); thread_guard g(t); do_something_in_current_thread();}
這樣在對象g析構的時候,會判定t是否為joinable,調用t.join(),無論其中是否拋出異常。
後台運行線程執行個體
void edit_document(std::string const& filename){ open_document_and_display_gui(filename); while(!done_editing()) { user_command cmd=get_user_input(); if(cmd.type==open_new_document) { std::string const new_name=get_filename_from_user(); std::thread t(edit_document,new_name); t.detach(); } else { process_user_input(cmd); } } }
傳遞參數給線程函數
傳遞參數給線程函數很簡單,只需要將函數參數附加線上程的建構函式之後即可。
舉例1
void f(int i,std::string const& s);std::thread t(f,3,”hello”);
一個線程對象t ,入口為函數f(3,"hello")
傳遞帶引用的參數時
舉例2
#include<iostream>#include<thread>using namespace std;void hello(int &i){ cout<<--i<<endl;}int main(){ int j=3; cout<<j<<endl; std::thread t(hello,ref(j)); t.join(); cout<<j<<endl; return 0;}
通過ref()來傳遞對象的引用,結果輸出:3,2,2
java並發編程與多線程編程有什聯絡
並發需要用多線程實現。
web開發一般是不用多線程,不過個別特殊的功能可能要用。
linux下C語言線程編程
void thread1()
{
int i;
for(i=0;i<8;i++)
{
sleep(1);
printf("thread1\n");
}
}
void thread2()
{
int i;
for(i=0;i<8;i++)
{
sleep(1) ;
printf("thread2\n");
}
}
int main()
{
pthread_t id;
int i,ret;
ret=pthread_create(&id,NULL,(void *)thread1,NULL);//建立線程1
if(ret!=0)
{
printf("Create thread error!\r\n");
exit(1);
}
ret=pthread_create(&id,NULL,(void *)thread2,NULL);//建立線程2
if(ret!=0)
{
printf("Create thread error!\r\n");
exit(1);
}
sleep(10000000);//確保兩個線程都結束後,再結束主線程
return 0;
}
上面程式建立了兩個線程,多次執行你會發現列印資訊順序是不一樣的,仔細揣摩會理解線程的並發執行的奧秘的。