2010-09-16 9 views
11

मैं बूस्ट लाइब्रेरी में एक नवागत हूं, और साझा कतार पर संचालित एक साधारण निर्माता और उपभोक्ता थ्रेड को लागू करने की कोशिश कर रहा हूं। मेरे उदाहरण दिया गया इस तरह दिखता है:सरल साझा डेटा लॉकिंग के लिए boost :: lock_guard का उपयोग करना

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

boost::mutex mutex; 
std::deque<std::string> queue; 

void producer() 
{ 
    while (true) { 
     boost::lock_guard<boost::mutex> lock(mutex); 

     std::cout << "producer() pushing string onto queue" << std::endl; 

     queue.push_back(std::string("test")); 
    } 
} 

void consumer() 
{ 
    while (true) { 
     boost::lock_guard<boost::mutex> lock(mutex); 

     if (!queue.empty()) { 
      std::cout << "consumer() popped string " << queue.front() << " from queue" << std::endl; 

      queue.pop_front(); 
     } 
    } 
} 

int main() 
{ 
    boost::thread producer_thread(producer); 
    boost::thread consumer_thread(consumer); 

    sleep(5); 

    producer_thread.detach(); 
    consumer_thread.detach(); 

    return 0; 
} 

इस कोड मैं उम्मीद के रूप में चलाता है, लेकिन जब main बाहर निकलता है, मैं

/usr/include/boost/thread/pthread/mutex.hpp:45:  
    boost::mutex::~mutex(): Assertion `!pthread_mutex_destroy(&m)' failed. 
consumer() popped string test from queue 
Aborted 

मिल (मुझे यकीन है कि अगर consumer से उत्पादन में प्रासंगिक है नहीं कर रहा हूँ स्थिति, लेकिन मैंने इसे छोड़ दिया है।)

क्या मैं बूस्ट के उपयोग में कुछ गलत कर रहा हूं?

उत्तर

8

आप अपने धागे (निर्माता उपभोक्ता) mutex ऑब्जेक्ट दें और फिर उन्हें अलग करें। वे हमेशा के लिए चलाने के लिए माना जाता है। फिर आप अपने प्रोग्राम से बाहर निकलें और mutex ऑब्जेक्ट अब मान्य नहीं है। फिर भी आपके धागे अभी भी इसका उपयोग करने का प्रयास करते हैं, वे नहीं जानते कि यह अब मान्य नहीं है। यदि आपने एनडीईबीयूजी परिभाषित किया था तो आपको एक कॉर्डम्प मिल जाएगा।

क्या आप डेमॉन एप्लिकेशन लिखने की कोशिश कर रहे हैं और यही थ्रेड को अलग करने का कारण है?

+0

मैं किसी विशेष प्रकार के ऐप को लिखने की कोशिश नहीं कर रहा हूं- मैं बूस्ट से परिचित होने की कोशिश कर रहा हूं। थ्रेड लाइब्रेरी। त्वरित डिबग सत्र के दौरान 'डिटेच' की कॉल डाली गई थी; यदि व्यवहार उन्हें हटा देता है तो व्यवहार समान होता है।मुझे शुरुआत में संदेह था कि प्रोग्राम से बाहर होने से पहले थ्रेड को रोकना होगा, इसलिए 'डिटेच' कॉल। – kfb

+7

तुरंत मुख्य धागे से बाहर निकलें और उपभोक्ता और निर्माता को अलग न करें। अपने उपभोक्ता और निर्माता काम तक मुख्य धागे में प्रतीक्षा करें। और जब वे समाप्त हो जाते हैं तो उनसे जुड़ें। और फिर मुख्य से बाहर निकलें। –

+0

यह समझ में आता है, और दावा रोकता है, धन्यवाद! – kfb

9

थोड़ा ऑफ-विषय लेकिन प्रासंगिक आईएमओ (... टिप्पणियों में आग के लिए इंतजार कर रहा है)।

यहां उपभोक्ता मॉडल बहुत लालची, लूपिंग और लगातार कतार पर डेटा की जांच कर रहा है। यदि यह आपके लॉक-एंड-पीक लूप की बजाय इंटर-थ्रेड सिग्नलिंग का उपयोग करते हुए डेटा उपलब्ध होने पर आपके उपभोक्ता धागे दृढ़ता से जागृत होते हैं तो यह अधिक कुशल (कम CPU चक्र अपशिष्ट) होगा। इस बारे में इस बारे में सोचें: जबकि कतार खाली है, यह अनिवार्य रूप से ताला हासिल करने की आवश्यकता से केवल तंग लूप है। आदर्श नहीं?

void consumer() 
{ 
    while (true) { 
     boost::lock_guard<boost::mutex> lock(mutex); 

     if (!queue.empty()) { 
      std::cout << "consumer() popped string " << queue.front() << " from queue" << std::endl; 

      queue.pop_front(); 
     } 
    } 
} 

मैं समझता हूं कि आप सीख रहे हैं लेकिन मैं इसे 'असली' कोड में उपयोग करने की सलाह नहीं दूंगा। पुस्तकालय सीखने के लिए हालांकि, यह ठीक है। आपके क्रेडिट के लिए, यह लॉक_गार्ड का उपयोग करने के तरीके को समझने के लिए आवश्यक से अधिक जटिल उदाहरण है, इसलिए आप उच्च लक्ष्य कर रहे हैं!

अंततः आप करेंगे सबसे अधिक संभावना का निर्माण (या बेहतर यदि उपलब्ध हो, पुन: उपयोग) एक कतार है कि श्रमिकों का संकेत है जब वे काम करने के लिए आवश्यक हैं, और आप तो lock_guard अपने कार्यकर्ता धागे के अंदर का उपयोग करेगा मध्यस्थता करने के लिए कोड साझा डेटा को एक्सेस करता है ।

+0

ऑफ-विषय, लेकिन निश्चित रूप से उपयोगी जानकारी, धन्यवाद! मैं मानता हूं कि यह एक बहुत लालची उपभोक्ता है, लेकिन यह पहले के परीक्षण से निकला था जिसमें कोई सिंक्रनाइज़ेशन नहीं था और मैं प्रोग्राम को लॉक करने के लिए प्रोत्साहित करने की कोशिश कर रहा था :) – kfb

5

जब main निकलता है, तो सभी वैश्विक वस्तुएं नष्ट हो जाती हैं। हालांकि, आपके धागे चलते रहेंगे। इसलिए आप समस्याओं से समाप्त होते हैं क्योंकि धागे हटाए गए ऑब्जेक्ट तक पहुंच रहे हैं।

नीचे की रेखा यह है कि आपको बाहर निकलने से पहले धागे को समाप्त करना होगा। हालांकि यह करने के लिए केवल मुख्य कार्यक्रम प्राप्त करना है (boost::thread::join का उपयोग करके) जब तक धागे चलने समाप्त नहीं हो जाते हैं। आप बहुत लंबे इंतजार से बचने के लिए दौड़ने के लिए धागे को सिग्नल करने का कोई तरीका प्रदान करना चाह सकते हैं।

दूसरा मुद्दा यह है कि डेटा नहीं होने पर भी आपका उपभोक्ता धागा चलना जारी रहता है। आप boost::condition_variable पर तब तक इंतजार करना चाहेंगे जब तक कि नया डेटा न हो।

संबंधित मुद्दे