2009-08-07 5 views
22

मैं काफी सरल थ्रेडेड एप्लिकेशन लिखने की कोशिश कर रहा हूं, लेकिन बूस्ट की थ्रेड लाइब्रेरी को नया करने के लिए नया हूं। एक साधारण परीक्षण कार्यक्रम मैं पर काम कर रहा हूँ है:(सरल) बूस्ट थ्रेड_ग्रुप प्रश्न

#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

मुझे लगता है कि समस्या थ्रेड_ग्रुप विनाशक के कारण होती है जिसे आपका प्रोग्राम बाहर निकलने पर बुलाया जाता है। थ्रेड समूह आपकी थ्रेड ऑब्जेक्ट्स को नष्ट करने की ज़िम्मेदारी लेना चाहता है। boost::thread_group दस्तावेज़ीकरण में भी देखें।

आप अपने थ्रेड ऑब्जेक्ट्स को स्टैक पर अपने मुख्य फ़ंक्शन के दायरे में स्थानीय चर के रूप में बना रहे हैं। इस प्रकार, जब प्रोग्राम बाहर निकलता है और थ्रेड_ग्रुप उन्हें हटाने की कोशिश करता है तो वे पहले से ही नष्ट हो चुके हैं।

एक समाधान के रूप में, नई साथ ढेर पर अपने धागा वस्तुओं को बनाने और thread_group उनके विनाश की देखभाल करते हैं:

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

आपको "नया" स्मृति आवंटन और इसे थ्रेड_ग्रुप में सौंपने के बीच इलिप्सिस को हटा देना चाहिए। अन्यथा अगर हस्तक्षेप कोड में कुछ गलत हो जाता है (यानी फेंकता है), तो आप धागे को रिसाव करेंगे। –

+0

हां, यह मामला प्रतीत होता है और बड़े कार्यक्रम में भी बग का कारण था। कामकाजी उदाहरण अब उपयोग करता है: // लॉन्च तीन धागे g.add_thread (नया बूस्ट :: थ्रेड (threaded_function, 10)); g.add_thread (नया बढ़ावा :: धागा (threaded_function, 10)); g.add_thread (नया बढ़ावा :: धागा (threaded_function, 10)); – RandomGuy

+1

यह सुनिश्चित करने का एक अच्छा तरीका है कि आप रिसाव नहीं करते हैं, यह std :: unique_ptr या इसी तरह के समाधान का उपयोग करना होगा और समूह_थ्रेड को थ्रेड प्रदान करने के लिए ptr.get() का उपयोग करना होगा। – Klaim

2

add_thread() आपके द्वारा पास किए गए थ्रेड का स्वामित्व लेता है। थ्रेड समूह थ्रेड को हटा देता है। इस उदाहरण में आप ढेर पर आवंटित स्मृति को हटा रहे हैं, काफी पूंजी अपराध।

सदस्य समारोह add_thread()

शून्य add_thread (धागा * thrd);

पूर्वशर्त:

अभिव्यक्ति thrd हटाना अच्छी तरह से गठित है और अपरिभाषित व्यवहार का कारण नहीं बनेगा।

प्रभाव:

लें बढ़ावा के स्वामित्व :: धागा वस्तु thrd द्वारा की ओर इशारा किया और समूह पर जोड़ें।

Postcondition:

इस-> आकार() एक के बाद बढ़ जाती है।

सुनिश्चित नहीं है कि आपके कोड में क्या गलत है, या यदि यह केवल उदाहरण बग है। अन्यथा कोड ठीक दिखता है।

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

0

यह ऊपर में से कोई भी वास्तव में सवाल का जवाब लग रहा है।

मुझे इसी तरह की समस्या से मुलाकात हुई। इस चेतावनी के परिणाम (।: 87: __pthread_mutex_lock: pthread_mutex_lock.c अभिकथन `म्युटेक्स -> _ डेटा _owner == 0 'विफल निरस्त किया गया।) यह है कि कभी कभी कार्यक्रम धागे रिसाव और एक boost_resource_error अपवाद का कारण होगा।

ऐसा लगता है कि प्रोग्राम join_all() के बाद निष्पादित करना जारी रखता है हालांकि अधिकांश धागे अभी भी चल रहे हैं (समाप्त नहीं हुए)।