2009-08-07 71 views
22

我想寫一個相當簡單的線程應用程序,但是對於boost的線程庫來說是新的。一個簡單的測試程序,我的工作是:(簡單)提升thread_group問題

#include <iostream> 
#include <boost/thread.hpp> 

int result = 0; 
boost::mutex result_mutex; 

boost::thread_group g; 

void threaded_function(int i) 
{ 
    for(; i < 100000; ++i) {} 

    { 
     boost::mutex::scoped_lock lock(result_mutex); 
     result += i; 
    } 
} 

int main(int argc, char* argv[]) 
{ 
    using namespace std; 

    // launch three threads 
    boost::thread t1(threaded_function, 10); 
    boost::thread t2(threaded_function, 10); 
    boost::thread t3(threaded_function, 10); 

    g.add_thread(&t1); 
    g.add_thread(&t2); 
    g.add_thread(&t3); 

    // wait for them 
    g.join_all(); 

    cout << result << endl; 

    return 0; 
} 

然而,當我編譯和運行這個程序,我得到的

$ ./test 
300000 
test: pthread_mutex_lock.c:87: __pthread_mutex_lock: Assertion `mutex->__data.__owner == 0' failed. 
Aborted 

輸出顯然,結果是正確的,但我很擔心關於這個錯誤信息,尤其是因爲真正的程序基本上具有相同的結構,所以在join_all()點卡住了。有人可以向我解釋發生了什麼事嗎?有沒有更好的方法來做到這一點,即啓動多個線程,將它們存儲在外部容器中,然後等待它們全部完成,然後再繼續該程​​序?

感謝您的幫助。

回答

25

我認爲你的問題是由你的程序退出時調用的thread_group析構函數引起的。線程組想要負責破壞線程對象。另請參閱boost::thread_group文檔。

您正在堆棧上創建線程對象,作爲主函數範圍內的局部變量。因此,它們在程序退出並且thread_group試圖刪除它們時已經被破壞了。

作爲一個解決方案,與堆上創建線程對象,讓thread_group採取銷燬的護理:

boost::thread *t1 = new boost::thread(threaded_function, 10); 
... 
g.add_thread(t1); 
... 
+0

您應該刪除「新」內存分配之間的省略號並將其傳遞給thread_group。否則,如果在干預代碼中出現錯誤(即拋出),則會泄漏該線程。 – 2009-08-08 13:10:05

+0

是的,這似乎是這種情況,也是大型程序中的錯誤原因。現在的工作示例使用: //啓動三個線程 g.add_thread(new boost :: thread(threaded_function,10)); g.add_thread(new boost :: thread(threaded_function,10)); g.add_thread(new boost :: thread(threaded_function,10)); – RandomGuy 2009-08-17 16:54:22

+1

確保不泄漏它的好方法是使用std :: unique_ptr 或類似的解決方案,並使用ptr.get()將該線程提供給group_thread。 – Klaim 2011-07-19 22:46:38

2

add_thread()取得您傳入的線程的所有權。線程組刪除線程。在這個例子中,你正在刪除堆棧中分配的內存,幾乎是一個嚴重的冒犯。

成員函數 add_thread()

空隙add_thread(螺紋* THRD);

前提

表達刪除THRD是 良好和不會導致 未定義的行爲。

影響:

升壓的取得所有權::線程 指向的對象THRD和 其添加到組。

後置條件

這 - >尺寸()增加一。

不知道這是你的代碼有什麼問題,或者這只是示例bug。否則代碼看起來很好。

24

如果您不需要把手你的線程,嘗試使用thread_group :: create_thread(),它可以不必在所有管理線程:

// Snip: Same as previous examples 

int main(int argc, char* argv[]) 
{ 
    using namespace std; 

    // launch three threads 
    for (int i = 0; i < 3; ++i) 
     g.create_thread(boost::bind(threaded_function, 10)); 

    // wait for them 
    g.join_all(); 

    cout << result << endl; 

    return 0; 
} 
+0

create_thread仍然返回線程的句柄http://www.boost.org/doc/libs/1_39_0/doc/html/thread/thread_management.html#thread.thread_management.threadgroup.create_thread。在這種情況下可以使用create_thread的原因是因爲與add_thread不同,線程組不承擔刪除線程的責任。 – shank22 2017-06-20 00:26:45

0

它看起來沒有任何的實際以上回答的問題。

我遇到了類似的問題。此警告的後果(:87:__pthread_mutex_lock:pthread_mutex_lock.c斷言`互斥 - > _ 數據 _owner == 0' 失敗 中止。)是有時程序將泄漏的線程並導致boost_resource_error異常。

原因看起來像程序在join_all()之後繼續執行,雖然大多數線程仍在運行(未終止)。