《線程管理:線程基本操作》

目錄

  • 線程管理
    • 啟動線程與(不)等待線程完成
    • 特殊情況下的等待(使用trycath或rall)
    • 后臺運行線程

線程管理

啟動線程與(不)等待線程完成

提供的函數對象被復制到新的線程的存儲空間中,函數對象的執行和調用都在線程的內存空間中進行。

class background_task
{
public:void operator()() const{do_something();do_something_else();}
};background_task f;std::thread my_thread(f);

注意,如果傳遞的是一個臨時變量,而不是一個命名變量,cpp編譯器會將其解析為函數聲明,而不是類型對象的定義。

當我們不等一個線程返回時,我們需要先將數據復制到線程中,這樣就不會產生訪問到已經銷毀的變量的問題了。

就如下所示,函數已經返回,線程依舊能夠訪問到局部變量

struct func
{int& i;func(int& i_) : i(i_) {}void operator() (){for (unsigned j=0 ; j<1000000 ; ++j){// 1 潛在訪問隱患:空引用do_something(i);}}
};
void oops()
{int some_local_state=0;func my_func(some_local_state);std::thread my_thread(my_func);my_thread.detach();
}
// 2 不等待線程結束
// 3 新線程可能還在運行

oops函數執行完成時,線程中的函數還在執行,還會訪問已經銷毀了的some_local_state變量,因為它持有的是該變量的指針。所以需要將數據復制到線程中,原始對象被銷毀也不妨礙線程中變涼了。當然,使用訪問局部變量的函數去創建線程不是很好。

此外,可以通過join()函數來確保線程在主函數完成前結束,可以確保局部變量在線程完成后才銷毀。

注意,只能對一個線程使用一次join,一旦使用過join,thread對象就不能再次匯入。

特殊情況下的等待(使用trycath或rall)

對于一個未銷毀的thread對象,如果想分離線程,在線程啟動后直接使用detach()進行分離。如果想等待線程,就需要思考好join位置,也要考慮拋出異常給join帶來的生命周期問題。

如下:使用了try/catch塊確保線程退出后函數才結束

struct func;	//定義代碼上面有
void f()
{int some_local_state = 0;func my_func(some_local_state);std::thread t(my_func);try{do_something_in_current_thread();}catch(...){t.join();throw;}t.join();
}

接下來介紹使用RALL等待線程完成

class thread_guard
{std::thread& t;
public:explicit thread_guard(std::thread& t_): t(t_) {}~thread_guard(){if(t.joinable())		//1t.join();			//2}thread_guard(thread_guard const&) = delete;		//3thread_guard& operator = (thread_guard const&) = delete;
};	
struct func;void f()
{int some_local_state = 0;func my_func(some_local_state);std::thread t(my_func);thread_guard g(t);do_something_in_current_thread();
}			//4

當線程執行到4,局部對象就要被逆序銷毀了。所以,對象g第一個被銷毀,線程在析構函數中,判斷是可join的,隨之執行join。所以即使do_something_in_current_thread函數跑出異常,這個銷毀依舊會發生。

還有個需要注意的地方,拷貝構造函數和拷貝賦值操作做標記為 =delete,編譯器不會自動生成。因為直接對對象進行拷貝或者賦值可能會丟失已經join的線程。

如果不想等待線程結束,可以分離線程,從而避免異常。不過這就打破了線程與std::thread對象聯系。即使線程仍然在后臺運行,detach操作也能確保std::terminate()在std::thread對象銷毀時才調用。

后臺運行線程

一個線程在后臺運行,就不能與主線程直接交互,分離的線程也不能join,不過c++保證,當線程退出時,相關資源能夠正確回收。

分離線程又稱守護線程。在UNIX中,守護線程指的是沒有任何顯式接口,并在后臺運行的線程。特點是長時間運行。

下面介紹一下分離線程的使用場景:

讓一個文字處理應用同時編輯多個文檔。每個文檔窗口看起來完全獨立,每個窗口也都有自己獨立的菜單選項,但他們卻運行在同一個應用實例中。一種內部處理方式是,讓每個文檔處理窗口擁有自己的線程。每個線程運行同樣代碼,并隔離不同窗口處理的數據。所以沒打開一個文檔就要啟動一個新線程,因為是對獨立文檔進行操作,所以沒有必要等待其他線程完成,可以讓文檔處理窗口運行在分離線程上。

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);		//1t.detach();									//2}else{process_user_input(cmd);}}}

用戶選擇打開一個新文檔,需要啟動一個新線程去打開新文檔(如step1),并分離線程(如step2)。與當前線程做出的操作一樣,新線程只不過是打開另一個文件而已。所以,edit_document函數可以復用,并通過傳參的形式打開新的文件。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/377042.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/377042.shtml
英文地址,請注明出處:http://en.pswp.cn/news/377042.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

scala特質_Scala的特質

scala特質Scala特質 (Scala traits) Traits in Scala are like interfaces in Java. A trait can have fields and methods as members, these members can be abstract and non-abstract while creation of trait. Scala中的特性類似于Java中的接口 。 特征可以具有作為成員的…

優化PHP代碼的40條建議(轉)

優化PHP代碼的40條建議 40 Tips for optimizing your php Code 原文地址&#xff1a;http://reinholdweber.com/?p3 英文版權歸Reinhold Weber所有&#xff0c;中譯文作者yangyang&#xff08;aka davidkoree&#xff09;。雙語版可用于非商業傳播&#xff0c;但須注明英文版作…

Iptables入門教程

轉自&#xff1a;http://drops.wooyun.org/tips/1424 linux的包過濾功能&#xff0c;即linux防火墻&#xff0c;它由netfilter 和 iptables 兩個組件組成。 netfilter 組件也稱為內核空間&#xff0c;是內核的一部分&#xff0c;由一些信息包過濾表組成&#xff0c;這些表包含內…

《線程管理:傳遞參數、確定線程數量、線程標識》

參考《c Concurrency In Action 》第二章做的筆記 目錄傳遞參數量產線程線程標識傳遞參數 thread構造函數的附加參數會拷貝至新線程的內存空間中&#xff0c;即使函數中的采納數是引用類型&#xff0c;拷貝操作也會執行。如果我們期待傳入一個引用&#xff0c;必須使用std::re…

手把手玩轉win8開發系列課程(14)

這節的議程就是——添加appbar appbar是出現在哪兒了&#xff0c;出現在屏幕的底部。他能使用戶能用手勢或者使用鼠標操作程序。metro UI 重點是在主要的控件使用許多控件&#xff0c;使其用戶使用win8電腦更加的方便。而appBar使其用戶體驗更好。在這節中&#xff0c;我將告訴…

No identities are available for signing 的解決辦法

今天重新上傳做好的app提交到app store&#xff0c;結果就出現標題上的錯誤。“No identities are available for signing”。 以后碰到這樣的問題按照下面幾個步驟來做&#xff1a; 進入Distribution -----下載發布證書 -----雙擊安裝-----重啟Xcode就能上傳了 其他細節 如果再…

半連接反連接

半連接&反連接 1. 半連接 半連接返回左表中與右表至少匹配一次的數據行&#xff0c;通常體現為 EXISTS 或者 IN 子查詢。左表驅動右表。只返回左表的數據&#xff0c;右表作為篩選條件。 可以用 EXISTS、 IN 或者 ANY 舉例&#xff1a;表t1和表t2做半連接&#xff0c;t…

匿名方法和Lambda表達式

出于MVVM學習的需要&#xff0c;復習下匿名方法和Lambda表達式&#xff0c;因為之前用的也比較少&#xff0c;所以用的也不是很熟練&#xff0c;Baidu下相關的知識&#xff0c;寫了這個Demo&#xff0c;目標是用簡單的方法展示這個怎么用。 這里偏重的和LINQ中的Lambda表達式 …

爛橘子

Problem Statement: 問題陳述&#xff1a; Given a matrix of dimension r*c where each cell in the matrix can have values 0, 1 or 2 which has the following meaning: 給定尺寸r * C的矩陣&#xff0c;其中矩陣中的每個單元可以具有其具有以下含義的值0&#xff0c;1或2…

android junit 測試程序

http://blog.csdn.net/to_cm/article/details/5704783 Assert.assertEquals(2, t); 斷言轉載于:https://www.cnblogs.com/wjw334/p/3714120.html

MySQL 8.0.22執行器源碼分析HashJoin —— BuildHashTable函數細節步驟

BuildHashTable函數細節步驟 該函數位置處于hash_join_iterator.cc 403 ~ 560行 step1&#xff1a;如果被驅動表迭代器沒有更多的行數&#xff0c;更新m_state為EOR&#xff0c;然后返回false&#xff0c;表明創建hash表失敗 if (!m_build_iterator_has_more_rows) {m_state…

《那些年啊,那些事——一個程序員的奮斗史》——125

距離離職交接的一個月時間還剩幾天&#xff0c;本來應該是平淡無事的&#xff0c;卻沒想到最后還是波瀾四起。昨天下班前&#xff0c;公司突然停了電。這本是件普通得不能再普通的事情&#xff0c;可沒想到過了一會來電了&#xff0c;或許是波峰電壓太大&#xff0c;或許是穩壓…

python中的元類_Python中的元類

python中的元類Python元類 (Python metaclass) A metaclass is the class of a class. A class defines how an instance of a class i.e.; an object behaves whilst a metaclass defines how a class behaves. A class is an instance of a metaclass. 元類是類的類。 一個類…

MySQL 8.0.22執行器源碼分析HashJoin —— 一些初始化函數的細節步驟

目錄InitRowBuffer&#xff08;101行~126行&#xff09;InitProbeIterator&#xff08;142行~153行&#xff09;*HashJoinIterator* 的Init&#xff08;155行~240行&#xff09;InitializeChunkFiles&#xff08;364行~401行&#xff09;InitWritingToProbeRowSavingFile&#…

c語言的宏定義學習筆記

宏定義 在預處理之前&#xff0c;c預處理器會對代碼進行翻譯&#xff0c;譬如用blank替換注釋&#xff0c;去掉多余的空格&#xff0c;刪除末尾的\來拼接行等。 例如&#xff1a; int /*注釋*/ x; 會被翻譯成 int x; printf("this is a s\ entence."); 會被翻譯成 pr…

攝氏溫度轉換華氏溫度_什么是攝氏溫度?

攝氏溫度轉換華氏溫度攝氏溫度 (Celsius) Celsius is a temperature measuring scale which as a SI unit derived from the seven base units stated and described by the International System of Units (SI). 攝氏溫度是一種溫度測量刻度&#xff0c;它是由國際單位制(SI)所…

別人的算法學習之路

http://www.cnblogs.com/figure9/p/3708351.html 我的算法學習之路 關于 嚴格來說&#xff0c;本文題目應該是我的數據結構和算法學習之路&#xff0c;但這個寫法實在太繞口——況且CS中的算法往往暗指數據結構和算法&#xff08;例如算法導論指的實際上是數據結構和算法導論&a…

git config命令使用第二篇——section操作,多個key值操作,使用正則

接上一篇&#xff0c;git config命令使用第一篇——介紹&#xff0c;基本操作&#xff0c;增刪改查:http://blog.csdn.net/hutaoer06051/article/details/8275069 1. 刪除一個section 命令參數 --remove-section 格式&#xff1a;git config [--local|--global|--system] --rem…

MySQL面試準備——64頁pdf

本筆記為以前整理的零碎的關于Mysql的知識點&#xff0c;有深入源碼的也有淺層的八股。已經被我整理成了一個pdf。 實習崗位正好也是和數據庫內核有關的&#xff0c;之后應該還會更新。做個整理&#xff0c;方便秋招的時候快速回顧吧。 鏈接&#xff1a;鏈接 提取碼&#xff1a…

python點圖_Python | 點圖

python點圖The dot plot is a type of data representation in which each data-point in the figure is represented as a dot. Dot plot underlies discrete functions unlike a continuous function in a line plot. Each value could be correlated but cannot be connecte…