并發(fā)編程2——線程啟動(dòng)、結(jié)束,創(chuàng)建線程多法、join,detach

目錄
  • 自己用代碼創(chuàng)建的其他線程
  • 需要從一個(gè)函數(shù)開始運(yùn)行
  • 當(dāng)這個(gè)函數(shù)運(yùn)行完畢的時(shí)候
  • 代表這個(gè)線程運(yùn)行結(jié)束

什么是多線程

不是一條線執(zhí)行,而是多條線,可以同時(shí)干多個(gè)事,即使一條線被堵住了,另一條也可以順利執(zhí)行


多線程

主線程應(yīng)該做的是等待子線程執(zhí)行完畢后,自己才能最終退出

如果想讓子線程不被OS強(qiáng)行終止

需要讓主線程一直保持運(yùn)行,不要讓主線程運(yùn)行完畢即可

thread類和join()函數(shù)

  • thread類是用來構(gòu)建子線程對(duì)象
  • join()函數(shù)是用來阻塞主線程,讓主線程等待子線程執(zhí)行完畢的函數(shù)

主線程阻塞到join()這里等待go()執(zhí)行完,當(dāng)子線程執(zhí)行完畢(然后子線程和主線程匯合),這個(gè)join()就會(huì)執(zhí)行完畢,主線程就可以繼續(xù)向下執(zhí)行。

如果沒有join()函數(shù)

  • 沒有join()函數(shù)

    就會(huì)發(fā)生異常


    異常

如果有join()函數(shù)

  • 有join()函數(shù)

就可以順利執(zhí)行


順利執(zhí)行

detach()的使用

detach()是可以讓主線程和子線程分離

  • 當(dāng)調(diào)用了detach()之后,與主線程關(guān)聯(lián)的thread對(duì)象就會(huì)失去與這個(gè)主線程的關(guān)聯(lián)
  • 此時(shí)這個(gè)子線程會(huì)駐留在后臺(tái)運(yùn)行(主線程和這個(gè)子線程失去聯(lián)系)

如果主線程提前退出了,子線程就會(huì)被C++運(yùn)行時(shí)庫接管,當(dāng)子線程執(zhí)行完的時(shí)候,運(yùn)行時(shí)庫會(huì)清理這個(gè)子線程的相關(guān)資源

這個(gè)線程一般被稱為守護(hù)進(jìn)程

detach()使用結(jié)果

detach()導(dǎo)致輸出的格式是亂的,隨機(jī)的,detach()后線程是不受控制的

detach()使用結(jié)果

什么是joinable()

如果一直沒有調(diào)用過join()和detach(),那么joinable()就是true
如果調(diào)用過,那么joinable()就是false

因?yàn)閖oin()和detach()不能同時(shí)調(diào)用,并且只能調(diào)用一次


其他創(chuàng)建線程的手法

之前的創(chuàng)建手法回顧

thread myobj(go)

這個(gè)go()是一個(gè)函數(shù),也是一個(gè)可調(diào)用對(duì)象

(或者說是類對(duì)象)也可以作為一個(gè)可調(diào)用對(duì)象

如果使用detach()

可以看到析構(gòu)函數(shù)只調(diào)用了一個(gè),這個(gè)析構(gòu)函數(shù)是析構(gòu)主線程的那個(gè)可調(diào)用對(duì)象的,因?yàn)樽泳€程那個(gè)還沒執(zhí)行完(藍(lán)色箭頭

使用detach()

如果使用join()

第一個(gè)析構(gòu)函數(shù)是子線程的
第二個(gè)析構(gòu)函數(shù)是主線程的

使用join()

“復(fù)制”還是“引用 or 指針”

如果我們用的是join(),那么用引用還是值傳遞都可以
如果用的是detach(),當(dāng)主線程退出的時(shí)候,myi變量會(huì)被系統(tǒng)自動(dòng)銷毀,那么這個(gè)時(shí)候子線程中就沒有東西可以執(zhí)行了,就會(huì)有異常。

需要注意的是這里的可調(diào)用對(duì)象ta進(jìn)入子線程后是直接復(fù)制了一份,所以拷貝構(gòu)造函數(shù)被執(zhí)行了。

  • 所以說還是用join穩(wěn)啊。

lambda表達(dá)式

  • 使用join()


    join()
  • 使用detach()


    detach()

小結(jié)

可以用函數(shù)、類對(duì)象、lambda表達(dá)式創(chuàng)建線程,作為線程的入口


博客示例代碼

  • thread和join()
#include <iostream>
#include <thread>

using namespace std;

void go()
{
    cout << "子線程開始執(zhí)行了!" << endl;
    cout << "子線程運(yùn)行完畢了!" << endl;
}

int main()
{
    thread myObj(go);

    myObj.join();
    cout << "主線程開始執(zhí)行了!" << endl;

    return 0;
}
  • detach()
#include <iostream>
#include <thread>

using namespace std;

void go()
{
    cout << "子線程開始執(zhí)行了!" << endl;

    cout << "子線程運(yùn)行完畢了1" << endl;
    cout << "子線程運(yùn)行完畢了2" << endl;
    cout << "子線程運(yùn)行完畢了3" << endl;
    cout << "子線程運(yùn)行完畢了4" << endl;
    cout << "子線程運(yùn)行完畢了5" << endl;
    cout << "子線程運(yùn)行完畢了6" << endl;
    cout << "子線程運(yùn)行完畢了7" << endl;
    cout << "子線程運(yùn)行完畢了8" << endl;
    cout << "子線程運(yùn)行完畢了9" << endl;
    cout << "子線程運(yùn)行完畢了10" << endl;
}

int main()
{
    thread myObj(go);

    // myObj.join();
    myObj.detach();
    cout << "fucking bitch 1" << endl;
    cout << "fucking bitch 2" << endl;
    cout << "fucking bitch 3" << endl;
    cout << "fucking bitch 4" << endl;
    cout << "fucking bitch 5" << endl;
    cout << "fucking bitch 6" << endl;
    cout << "fucking bitch 7" << endl;
    cout << "fucking bitch 8" << endl;
    cout << "fucking bitch 9" << endl;
    cout << "fucking bitch 10" << endl;

    return 0;
}
  • 類對(duì)象
#include <iostream>
#include <thread>

using namespace std;

class TA
{
public:
    int m_i;

    TA(int i) : m_i(i) { cout << "TA()構(gòu)造函數(shù)被執(zhí)行" << endl; }
    TA(const TA& ta) : m_i(ta.m_i) { cout << "TA()拷貝構(gòu)造函數(shù)被執(zhí)行" << endl; }
    ~TA() { cout << "~TA()析構(gòu)函數(shù)被執(zhí)行" << endl; }

    void operator() ()
    {
        cout << "m_i1的值為:" << m_i << endl;
        cout << "m_i2的值為:" << m_i << endl;
        cout << "m_i3的值為:" << m_i << endl;
        cout << "m_i4的值為:" << m_i << endl;
        cout << "m_i5的值為:" << m_i << endl;
        cout << "m_i6的值為:" << m_i << endl;
        cout << "m_i7的值為:" << m_i << endl;
        cout << "m_i8的值為:" << m_i << endl;
    }
};

int main()
{
    int myi = 6;
    TA ta(myi);
    
    thread myObj(ta);

    myObj.join();
    //myObj.detach();

    cout << "fucking bitch 1" << endl;
    cout << "fucking bitch 2" << endl;
    cout << "fucking bitch 3" << endl;
    cout << "fucking bitch 4" << endl;
    cout << "fucking bitch 5" << endl;
    cout << "fucking bitch 6" << endl;
    cout << "fucking bitch 7" << endl;
    cout << "fucking bitch 8" << endl;
    cout << "fucking bitch 9" << endl;
    cout << "fucking bitch 10" << endl;

    return 0;
}
  • lambda表達(dá)式
#include <iostream>
#include <thread>

using namespace std;


int main()
{
    auto mylambdathread = []
    {
        cout << "我的線程開始執(zhí)行了" << endl;

        cout << "我的線程執(zhí)行結(jié)束了" << endl;
        cout << "我的線程執(zhí)行結(jié)束了" << endl;
        cout << "我的線程執(zhí)行結(jié)束了" << endl;
        cout << "我的線程執(zhí)行結(jié)束了" << endl;
    };

    thread myobj(mylambdathread);
    // myobj.join();
    myobj.detach();

    cout << "Fucking bitch" << endl;

    return 0;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容