2012-06-25 98 views
2

Another SO thread解釋瞭如何使用thread::native_handle來執行C++線程API之外的事情(例如,設置線程的優先級)。要點是:如何拖延產卵線程足夠長的時間來產卵線程做些什麼?

std::thread t(functionToRun); 
auto nh = t.native_handle()); 
// configure t using nh   

這種方法的問題是,可能functionToRun代碼之前執行的時間(包括完成)的任意量來配置噸結束。

我相信我們可以防止這種情況發生如下(未經測試):

std::atomic<bool> configured(false); 

std::thread t([&]{ while (!configured); // spin until configured is true 
        functionToRun(); }); 
auto nh = t.native_handle(); 
// configure t using nh 
configured = true; 

不幸的是,這會導致產生的線程自旋等待configured成爲事實。在配置完成之前,產生的線程會被阻塞。實現這一

一種方法似乎是使用互斥(也未經測試):

std::mutex m; 

std::unique_lock<std::mutex> lock(m); 

std::thread t([&]{ std::lock_guard<std::mutex> lg(m); // block until m available 
        functionToRun(); }); 
auto nh = t.native_handle(); 
// configure t using nh 
lock.unlock();           // allow t to continue 

這看起來像它應該工作,但是,從概念上講,它似乎是一個condvar更適合這份工作指示何時滿足條件(配置完成)。但是,使用condvar需要上述所有內容以及condvar,並且需要處理虛假喚醒的可能性,據我所知,這對於互斥鎖來說不是問題。

有沒有更好的方法來產生一個線程,然後讓它立即停止,以便我可以使用它的本地句柄來配置它,然後再允許它進一步運行?

+1

在產生的線程('functionToRun()')中進行等待而不是產生的線程會更有意義嗎?也就是說,剛產生的線程進入睡眠狀態,直到產卵者發出「配置完成,繼續」信號爲止。 – DevSolar

+2

@DevSolar:這就是代碼應該做的事情。產卵線程抓取互斥體,因此產生的線程在嘗試獲取它時會阻塞。當產卵線程解鎖互斥體(表明配置已完成)時,產生的線程可以繼續。請注意,派生函數不是functionToRun,它是調用functionToRun的lambda生成的閉包。 – KnowItAllWannabe

回答

7

當我希望延遲線程主功能的啓動,直到某些外部配置完成時,我使用未來。這樣可以避免自旋等待,並且具有與互斥鎖或condvar相同的阻止屬性,但提供了更清晰的意圖。使用這種模式,你可以寫你的例子如:

std::promise<void> p; 
std::thread t([&p]{ 
    p.get_future().wait(); 
    thread_func(); 
} 

auto nh=t.native_handle(); 
// configure nh 
p.set_value(); 

我特別喜歡使用這種模式與shared_future多線程測試---這樣就可以保證所有的線程正在運行,並準備去測試開始之前。