2009-08-07 42 views
22

Tôi đang cố gắng viết một ứng dụng luồng khá đơn giản, nhưng mới để thư viện chủ đề của boost. Một chương trình thử nghiệm đơn giản, tôi đang làm việc trên là:(đơn giản) tăng thread_group câu hỏi

#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; 
} 

Tuy nhiên, khi tôi biên dịch và chạy chương trình này tôi nhận được một sản lượng

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

Rõ ràng, kết quả là đúng nhưng tôi lo lắng về thông báo lỗi này, đặc biệt là vì chương trình thực sự, mà về cơ bản có cùng cấu trúc, đang bị kẹt tại điểm join_all(). Ai đó có thể giải thích cho tôi điều gì đang xảy ra? Có cách nào tốt hơn để thực hiện việc này, tức là khởi chạy một số luồng, lưu trữ chúng trong một vùng chứa bên ngoài và sau đó chờ cho tất cả chúng hoàn thành trước khi tiếp tục chương trình không?

Cảm ơn sự giúp đỡ của bạn.

Trả lời

25

Tôi nghĩ rằng vấn đề của bạn là do destructor thread_group được gọi khi chương trình của bạn thoát. Nhóm chủ đề muốn chịu trách nhiệm về việc hủy các đối tượng chuỗi của bạn. Xem thêm trong tài liệu boost::thread_group.

Bạn đang tạo đối tượng chuỗi của mình trên ngăn xếp dưới dạng biến cục bộ trong phạm vi chức năng chính của bạn. Do đó, chúng đã bị hủy khi chương trình thoát và thread_group cố gắng xóa chúng.

Là một giải pháp, tạo các đối tượng thread của bạn trên heap với mới và để cho các thread_group chăm sóc hủy diệt của họ:

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

Bạn nên xóa dấu chấm lửng giữa phân bổ bộ nhớ "mới" và giao nó cho nhóm thread_group. Nếu không, nếu có điều gì đó sai (tức là ném) trong mã can thiệp, bạn sẽ làm rò rỉ sợi chỉ. –

+0

Có, điều này có vẻ như là trường hợp và cũng là nguyên nhân của lỗi trong chương trình lớn hơn. Ví dụ làm việc hiện sử dụng: // khởi chạy ba luồng g.add_thread (chuỗi tăng mới :: thread (threaded_function, 10)); g.add_thread (new boost :: thread (threaded_function, 10)); g.add_thread (new boost :: thread (threaded_function, 10)); – RandomGuy

+1

Cách tốt nhất để đảm bảo bạn không bị rò rỉ là sử dụng lệnh std :: unique_ptr hoặc giải pháp tương tự và sử dụng ptr.get() để cung cấp luồng cho group_thread. – Klaim

2

add_thread() nhận quyền sở hữu chuỗi bạn chuyển vào. Nhóm chủ đề xóa chủ đề. Trong ví dụ này, bạn đang xóa bộ nhớ được cấp phát trên stack, khá nhiều vi phạm vốn.

chức năng thành viên add_thread()

trống add_thread (Chủ đề * thrd);

kiện tiên quyết:

Khái niệm xóa thrd là tốt được hình thành và sẽ không dẫn đến hành vi không xác định.

Effects:

Take Ownership của boost :: chủ đề đối tượng được trỏ đến bởi thrd và thêm nó vào nhóm.

hậu:

this-> size() là một tăng.

Không chắc đó là điều gì sai trong mã của bạn hay nếu đây chỉ là lỗi mẫu. Nếu không mã sẽ tốt.

24

Nếu bạn không cần một xử lý cho chủ đề của bạn, hãy thử sử dụng thread_group :: create_thread() làm giảm bớt nhu cầu quản lý luồng ở tất cả:

// 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 vẫn trả về một xử lý cho chuỗi http://www.boost.org/doc/libs/1_39_0/doc/html/thread/thread_management.html#thread.thread_management.threadgroup.create_thread. Lý do create_thread có thể được sử dụng trong trường hợp này là bởi vì không giống như add_thread, nhóm thread không chịu trách nhiệm xóa luồng. – shank22

0

Có vẻ như không có câu nào trên thực tế trả lời câu hỏi.

Tôi đã gặp sự cố tương tự. Hậu quả của cảnh báo này (pthread_mutex_lock.c: 87: __pthread_mutex_lock: Assertion `mutex -> _ dữ liệu. _owner == 0 'không thành công. Hủy bỏ) là đôi khi chương trình sẽ làm rò rỉ luồng và gây ra ngoại lệ boost_resource_error.

Lý do trông giống như chương trình tiếp tục thực thi sau khi join_all() mặc dù hầu hết các chủ đề vẫn đang chạy (không bị chấm dứt).

Các vấn đề liên quan