2.1線程管理基礎(chǔ)

啟動(dòng)線程

使用C++線程庫啟動(dòng)線程可以歸結(jié)為構(gòu)造std::thread對(duì)象:

void do_some_work();
std::thread my_thread(do_some_work);

std::thread可以用可調(diào)用(callable)類型構(gòu)造舞萄,將帶有函數(shù)調(diào)用符類型的實(shí)力傳入std::thread類中,替換默認(rèn)的構(gòu)造函數(shù)舔示。

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

【注意】當(dāng)函數(shù)對(duì)象傳入到線程構(gòu)造函數(shù)中時(shí)借杰,要避免語法解析过吻,如果傳遞了一個(gè)臨時(shí)變量而不是一個(gè)明明的變量;C++編譯器會(huì)將其解析為函數(shù)聲明蔗衡,而不是類型對(duì)象的定義纤虽。
例如:

std::thread my_thread(background_task());

使用前面命名函數(shù)對(duì)象的方式,或使用多組括號(hào)绞惦,或使用新統(tǒng)一的初始化語法逼纸,或者使用lambda表達(dá)式,可以避免這個(gè)問題济蝉。如:

std::thread my_thread((background_task()));
std::thread my_thread{background_task()};
std::thread my_thread([]{
  do_something();
  do_something_else();
});

啟動(dòng)了線程需要明確是要等待線程結(jié)束杰刽,還是讓其自主運(yùn)行菠发。如果std::thread對(duì)象銷毀之前還沒有做出決定,程序就會(huì)終止贺嫂,因此即便有異常存在滓鸠,也需要確保線程能夠正確的加入(joined)或分離(detached)

2.1.2等待線程的完成

只能對(duì)一個(gè)線程使用一次join();一旦使用過join(),std::thread對(duì)象就不能再次加入,當(dāng)對(duì)其使用joinable()時(shí)涝婉,將返回否(false)哥力。

特殊情況下的等待

避免應(yīng)用被拋出的異常所終止,就需要做出一個(gè)決定墩弯。通常當(dāng)傾向于在無異常的情況下使用join()時(shí),需要在異常處理的過程中調(diào)用join()寞射,從而避免生命周期的問題渔工。

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();
}

如何確保線程在函數(shù)之前結(jié)束?
使用資源獲取即初始化方式(RAII桥温, Resource Acquisition Is Initialization)引矩,并且提供一個(gè)類,在析構(gòu)函數(shù)中使用join()

class thread_guard
{
  std::thread& t;
  public:
  explicit thread_guard(std::thread& t_): t(t_) {}
  ~thread_guard()
  {
    if(t.joinable()) // 1
    {
      t.join(); // 2
    }
  } 
  thread_guard(thread_guard const&)=delete; // 3
  thread_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();
}

后臺(tái)運(yùn)行程序

對(duì)一個(gè)std::thread對(duì)象使用detach()就會(huì)將這個(gè)線程擱置在后臺(tái)運(yùn)行侵浸,這就意味著不能與這個(gè)線程產(chǎn)生直接交互旺韭。
因?yàn)镃++運(yùn)行庫保證,當(dāng)線程退出時(shí)掏觉,其相關(guān)資源的能夠正確的回收区端,所以后臺(tái)線程的歸屬和控制都會(huì)交給C++運(yùn)行庫處理。
分離線程的使用場景澳腹?
通常织盼, 稱分離線程為守護(hù)線程( daemon threads) 。 在UNIX中守護(hù)線程是指酱塔, 運(yùn)行在后臺(tái)沥邻,且沒有任何可用用戶接口的線程。 這種線程的特點(diǎn)就是長時(shí)間運(yùn)行羊娃;它們的生命周期可能會(huì)從某一個(gè)應(yīng)用起始到結(jié)束唐全, 也會(huì)在后臺(tái)執(zhí)行諸如監(jiān)事文件系統(tǒng)的任務(wù), 還有可能對(duì)未使用的緩存進(jìn)行清理蕊玷, 亦或?qū)?shù)據(jù)結(jié)構(gòu)進(jìn)行優(yōu)化邮利。 另一方面, 它也使用分離線程的另一種機(jī)制集畅, 確定線程什么時(shí)候結(jié)束近弟, 或者在“發(fā)后即忘”( fire and forget) 的任務(wù)在哪里使用到了這個(gè)線程。

使用條件
為了從一個(gè) std::thread 對(duì)象中分離一個(gè)線程( 前提是有一個(gè)可進(jìn)行分離的線程) :你不能對(duì)沒有執(zhí)行線程的 std::thread 對(duì)象使用detach()挺智。

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末祷愉,一起剝皮案震驚了整個(gè)濱河市窗宦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌二鳄,老刑警劉巖赴涵,帶你破解...
    沈念sama閱讀 216,843評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異订讼,居然都是意外死亡髓窜,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門欺殿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來寄纵,“玉大人,你說我怎么就攤上這事脖苏〕淌茫” “怎么了?”我有些...
    開封第一講書人閱讀 163,187評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵棍潘,是天一觀的道長恃鞋。 經(jīng)常有香客問我,道長亦歉,這世上最難降的妖魔是什么恤浪? 我笑而不...
    開封第一講書人閱讀 58,264評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮肴楷,結(jié)果婚禮上水由,老公的妹妹穿的比我還像新娘。我一直安慰自己阶祭,他們只是感情好绷杜,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評(píng)論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著濒募,像睡著了一般鞭盟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上瑰剃,一...
    開封第一講書人閱讀 51,231評(píng)論 1 299
  • 那天齿诉,我揣著相機(jī)與錄音,去河邊找鬼晌姚。 笑死粤剧,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的挥唠。 我是一名探鬼主播抵恋,決...
    沈念sama閱讀 40,116評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼宝磨!你這毒婦竟也來了弧关?” 一聲冷哼從身側(cè)響起盅安,我...
    開封第一講書人閱讀 38,945評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎世囊,沒想到半個(gè)月后别瞭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,367評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡株憾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評(píng)論 2 333
  • 正文 我和宋清朗相戀三年蝙寨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嗤瞎。...
    茶點(diǎn)故事閱讀 39,754評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡墙歪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出猫胁,到底是詐尸還是另有隱情箱亿,我是刑警寧澤,帶...
    沈念sama閱讀 35,458評(píng)論 5 344
  • 正文 年R本政府宣布弃秆,位于F島的核電站,受9級(jí)特大地震影響髓帽,放射性物質(zhì)發(fā)生泄漏菠赚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評(píng)論 3 327
  • 文/蒙蒙 一郑藏、第九天 我趴在偏房一處隱蔽的房頂上張望衡查。 院中可真熱鬧,春花似錦必盖、人聲如沸拌牲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽塌忽。三九已至,卻和暖如春失驶,著一層夾襖步出監(jiān)牢的瞬間土居,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評(píng)論 1 269
  • 我被黑心中介騙來泰國打工嬉探, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留擦耀,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,797評(píng)論 2 369
  • 正文 我出身青樓涩堤,卻偏偏與公主長得像眷蜓,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子胎围,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容