C++多執行緒中的join, detach, joinable

  • 2020 年 2 月 16 日
  • 筆記

       thread是C++11中提供多執行緒編程的模組,使用的時候需要包含<thread>頭文件。

       首先我們先來看一下簡單的hello world的多執行緒的程式碼(win10下vs2019)

       這個創建的方式就是以函數作為一個入口,創建了一個子執行緒,那麼創建的語句就是第11行程式碼所示,所傳入的參數就是入口的函數名。在創建了這個子執行緒之後,這個子執行緒就開始運行了,同時主執行緒也不停的往下運行,當碰到t.join()這句程式碼的時候,就表示主執行緒需要等待子執行緒運行結束回收掉子執行緒的資源後,再往下運行,否則就會產生一種情況:當子執行緒還沒有運行完主執行緒先運行完了,那麼就會結束這個進程,從而中斷了子執行緒的運行。因此join()函數的作用就是使主執行緒在此阻塞,等待子執行緒運行結束並回收其資源,再往下運行。

       當然我們可以用this_thread::get_id()這個函數來驗證這個子執行緒和主執行緒是不同的兩個執行緒,結果如下圖所示

       可見兩個執行緒的id是不同的。

       然後我們再看一下下面的這個圖,用的是detach函數:

       從這個圖中我們可以發現fun和main是交叉著輸出的,並不是先輸出fun中的內容,那麼detach的作用就是將主執行緒與子執行緒分離,主執行緒將不再等待子執行緒的運行,也就是說兩個執行緒同時運行,當主執行緒結束的時候,進程結束。

       那麼可能就會產生一些疑問,那這樣不就中斷了子執行緒的運行嗎?

       其實不是,在detach的時候,這個子執行緒將脫離主執行緒的控制,子執行緒獨立分離出去並在後台運行。當主執行緒結束的時候,進程也就結束,所以子執行緒的輸出不再顯示出來,但是不會中斷,會在後台繼續運行,當子執行緒運行完以後,資源會被運行時庫進行回收。

       joinable()函數是一個布爾類型的函數,他會返回一個布爾值來表示當前的執行緒是否是可執行執行緒(能被join或者detach),因為相同的執行緒不能join兩次,也不能join完再detach,同理也不能detach,所以joinable函數就是用來判斷當前這個執行緒是否可以joinable的。通常不能被joinable有以下幾種情況:

       1)由thread的預設構造函數而造成的(thread()沒有參數)。

       2)該thread被move過(包括move構造和move賦值)。

       3)該執行緒被join或者detach過。