C++日記——Day36:線程啓動、結束,創建線程多法、join,detach

線程運行的開始和結束

整個進程是否執行完畢的標誌是 主線程是否執行完,如果主線程執行完畢了,就代表整個進程執行完畢了;

此時,一般情況,如果其他子線程還沒有執行完畢,那麼這些子線程也會被操作系統強行終止。

所以,一般情況下,如果大家想保持子線程(自己用代碼創建的線程)的運行狀態,大家就要讓主線程一直保持運行,不要讓主線程運行完畢。(這條規律有例外)

#include <thread>

vodi myprint() //自己創建的線程也要從一個函數開始執行
{
    cout << "start thread" << endl;
    cout << "end thread" << endl;
}

int main(){
    thread myobj(myprint);  //thread對象的構造函數接受的是一個可調用對象,
                            //創建了線程,線程執行起點myprint();
    myobj.join();  //說白了,就是阻塞主線程,讓主線程等待子線程執行完畢,然後主線程於 
                   //子線程匯合繼續執行,當子線程執行完畢,join()就執行完畢,主線程繼 
                   //續執行
    cout << "good luck" << endl;



    return 0;
}

上面代碼,有兩個線程再跑,相當於整個程序的執行有兩條線同時在走,基石一條線被堵住了,另外一條線會繼續執行。

thread:是個標準庫中的類。

join():加入,匯合,說白了就是阻塞主線程,讓主線程等待子線程執行完畢,join()就執行完畢。

通常情況,主線程執行完畢了,但子線程沒執行完,這種程序是不穩定的

一個書寫良好的程序應該是主線程等待子線程執行完畢後才退出。

例外:detach():

傳統多線程程序,主線程要等待子線程執行完畢後,在退出,detach分離,主線程不和子線程匯合,主線程和子線程分別執行自己的,主線程並不影響子線程的執行。

爲什麼引入detach:我們創建了很多子線程,讓主線程逐個等待子線程結束,這種編程方法不太好,所以我們引入detach();一旦detach()之後(不建議較多使用detach),與這個主線程關聯的thread對象就會失去與這個主線程的關聯,此時這個子線程就會駐留在後臺運行

主線程跟該子線程失去聯繫,這個子線程就相當於被C++運行時庫接管了,當這個子線程執行完成後由運行時庫負責清理該線程相關資源(守護線程)

#include <thread>

vodi myprint() //自己創建的線程也要從一個函數開始執行
{
    cout << "start thread" << endl;
    cout << "end thread" << endl;
}

int main(){
    thread myobj(myprint);  ;
    myobj.detach();  
    cout << "good luck" << endl;
    return 0;
}

一旦調用了detach()就不能在join();

joinable():判讀是否可以成功join()或者detach()的。返回true,或者false(返回true時可以join或者detach,返回false時不行)

#include <thread>

vodi myprint() //自己創建的線程也要從一個函數開始執行
{
    cout << "start thread" << endl;
    cout << "end thread" << endl;
}

int main(){
    thread myobj(myprint); 

    if(myobj.joinable()){  //true
        cout << "joinable() == ture" << endl;
    }

    myobj.detach();  

    if(!myobj.joinable()){   //false
        cout << "joinable() == false" << endl;
    }

    cout << "good luck" << endl;
    return 0;
}

 

其他創建線程方法

1、用類對象

疑問:一旦定義detach()那麼,主線程執行結束了,那麼ct對象還在麼?如果不在了,detach的線程怎麼執行?

這個對象不在了,但是detach的對象可以正常執行,因爲這個對象實際上是被複制到線程中去,所以執行完主線程後,ct會被銷燬,但是所複製的TA對象依舊存在。所以你這個TA對象裏沒有引用,沒有指針,就不會有問題。

class CT
{
public:
    void operator()() //可調用對象
    {

    }
};

int main(){
    CT ct;
    thread myobj(ct);
    myobj.join();
}

2、lambda表達式

auto mylambda = [] (){
    cout << "lambda" << endl;
}

int main(){
    thread myobj(mylambda);
    //myobj.join();
    myobj.detach();
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章