2013-11-25 44 views
4

我讀了一些關於manuals線程和我來一想,他們表現出的代碼是不是安全:螺紋連接問題

std::cout << "starting first helper...\n"; 
std::thread helper1(foo); 

std::cout << "starting second helper...\n"; 
std::thread helper2(bar); 

std::cout << "waiting for helpers to finish..." << std::endl; 
helper1.join(); // #1 NOT SAFE 
helper2.join(); // #2 NOT SAFE 

我相信這個代碼是不是絕對安全的。如果我沒有弄錯沒有保證helper1helper2已經處於可連接狀態時,控制到達線路標記爲#1#2。線程仍然可以不啓動,並且此時沒有標識符。這將導致未捕獲的異常從std::thread::join()

我認爲下面的代碼解決了這個問題被拋出。我對嗎?

std::cout << "starting first helper...\n"; 
std::thread helper1(foo); 

std::cout << "starting second helper...\n"; 
std::thread helper2(bar); 

std::cout << "waiting for helpers to finish..." << std::endl; 
while (helper1.joinable() == false) { } 
helper1.join(); // #1 SAFE 
while (helper2.joinable() == false) { } 
helper2.join(); // #2 SAFE 
+3

不能線程是可連接,即使它沒有啓動? HTTP://計算器。com/questions/15994650/c11-safely-join-a-thread-without-using-a-try-catch-block – doctorlove

+0

@doctorlove'std :: thread :: joinable如果線程對象標識一個活動的執行線程,則返回true ,否則爲假。我認爲它不能。 – Kolyunya

+0

你在引用什麼? – doctorlove

回答

5

一個std::threadjoinable如果它包含尚未join版或detatch ED線程狀態。

A std::thread通過非默認構造獲得線程狀態,或者從另一個std::thread編輯move。它在move編輯時丟失了。

有一個在建設完成後獲得線程的狀態沒有延遲。當線程函數完成時它不會消失。所以沒有那個問題。

有一個問題,如果代碼拋出上面,你將失敗joindetatch,在程序關閉導致壞消息。在RAII包裝始終包裹std::thread避免這種情況,或者只是使用std::async返回void和包裝所產生的std::future相似(因爲標準說,它的塊在析構函數,但微軟的落實沒有,所以你不能,如果它會或不信任)。

+0

謝謝你的回答。目前我無法訪問該標準。您是否引用了標準或在哪裏可以閱讀有關該主題的更多信息? – Kolyunya

+0

從'std :: async'的VC'std :: futures'不要在dtor中阻塞? – inf

+0

@bamboon是的,沒錯。我自己測試過。 –

3

您正在以過於複雜的方式感知線程。 join有安全加入一個線程。只需使用:

std::thread my_thread(my_main); 
my_thread.join(); 
2

std::thread::thread(F&& f, Args&&... args)構造有這個後置條件:

後續條件:get_id() != id()*this代表新啓動的線程。

joinable()定義是

返回:get_id() != id()

因此構造函數的後置條件是該對象是可連接,並且後置條件一旦構造完成適用。操作系統是否確實啓動了線程並不重要,thread對象仍然知道新線程的ID,並且仍然可以等待它完成並加入它。