15

प्रवास के एप्पल के कन्करेंसी प्रोग्रामिंग गाइड के धागे अनुभाग से दूर, वहाँ
Changing Producer-Consumer Implementations जो दावा है कि ठेठ multistep pthread म्युटेक्स + हालत चर कार्यान्वयन GCD का उपयोग कर सरल किया जा सकता है।ऐप्पल डॉक्टर का जीसीडी निर्माता-उपभोक्ता समाधान गलत है?

प्रेषण कतारों के साथ

, आप एक ही कॉल में उत्पादक और उपभोक्ता कार्यान्वयन को आसान बनाने में कर सकते हैं:

dispatch_async(queue, ^{ 
    // Process a work item. 
}); 

अपने निर्माता काम होता है तो किया जाना है, यह सब करना पड़ता है उस कतार को उस कतार में जोड़ें और कतार को आइटम को संसाधित करने दें।

निर्माता-उपभोक्त समस्या भी घिरा-बफर समस्या के रूप में जाना जाता है, फिर भी ऊपर एक बफर के कोई जिक्र नहीं है, इसके लिए बाध्य या उपभोक्ता, अकेले आदेश से अधिक से बचने के लिए निर्माता & उपभोक्ता अवरुद्ध/रन के तहत।

यह एक वैध समाधान कैसे हो सकता है?

+0

लेकिन इस मामले में केवल एक प्रदर्शन हिट परिप्रेक्ष्य से बेहतर होगा, जिसमें निर्माता और उपभोक्ता एक साथ चलने वाले 2 धागे होते हैं, सिस्टम इनिट के दौरान शुरू होते हैं या जीसीडी मार्ग पर जाते हैं जो उत्पादक के पास अधिक डेटा जोड़ने के लिए एसिंक थ्रेड भेज देगा (चूंकि धागे को प्रेषित करने से भी अपना प्यारा समय लगता है)। – Ichthyocentaurs

+0

कतार बफर है। –

उत्तर

22

समाधान में है कि एप्पल दस्तावेज़ में वर्णित:

  1. कोई बफर क्योंकि कोई बफर की जरूरत है नहीं है;
  2. सिस्टम लोड बाध्य है;
  3. उपभोक्ता कार्य हैं।

कहें कि आपके पास कई उत्पादक और उपभोक्ता हैं, निर्माता एक साझा बफर में डेटा डालते हैं और उपभोक्ता उस साझा बफर से डेटा पढ़ते हैं। एक सेफफोरे या मॉनिटर का उपयोग साझा बफर तक पहुंच को सिंक्रनाइज़ करने के लिए किया जाता है, और बफर आकार तय किया जाता है ताकि उत्पादित होने वाली दर के अनुसार उत्पादित होने वाली मात्रा की मात्रा को सीमित किया जा सके, इसलिए निर्माता को थ्रोटलिंग किया जा सके।

ग्रैंड सेंट्रल डिस्पैच के तहत, उपभोक्ता एक कतार में भेजे गए कार्य हैं। चूंकि कार्य उद्देश्य-सी ब्लॉक हैं, इसलिए किसी निर्माता को डेटा को डेटा के बारे में बताने के लिए बफर की आवश्यकता नहीं होती है: उद्देश्य-सी ब्लॉक स्वचालित रूप से उन वस्तुओं को कैप्चर करते हैं जिन्हें वे संदर्भित करते हैं।

उदाहरण के लिए:

// Producer implementation 
while (…) { 
    id dataProducedByTheProducer; 

    // Produce data and place it in dataProducedByTheProducer 
    dataProducedByTheProducer = …; 

    // Dispatch a new consumer task 
    dispatch_async(queue, ^{ 
     // This task, which is an Objective-C block, is a consumer. 
     // 
     // Do something with dataProducedByTheProducer, which is 
     // the data that would otherwise be placed in the shared 
     // buffer of a traditional, semaphore-based producer-consumer 
     // implementation. 
     // 
     // Note that an Objective-C block automatically keeps a 
     // strong reference to any Objective-C object referenced 
     // inside of it, and the block releases said object when 
     // the block itself is released. 

     NSString *s = [dataProducedByTheProducer …]; 
    }); 
} 

निर्माता डेटा यह उत्पादन कर सकते हैं के रूप में कई उपभोक्ता कार्य कर सकती हैं। हालांकि, इसका मतलब यह नहीं है कि जीसीडी उपभोक्ता कार्यों को उसी दर पर आग लगाएगी। जीसीडी मौजूदा सिस्टम लोड के अनुसार निष्पादित कार्यों की मात्रा को नियंत्रित करने के लिए ऑपरेटिंग सिस्टम की जानकारी का उपयोग करता है। निर्माता खुद को थ्रॉटल नहीं किया जाता है, और ज्यादातर मामलों में यह जीसीडी के आंतरिक भार संतुलन के कारण नहीं होना चाहिए।

यदि बहुत निर्माता रुके वास्तविक जरूरत, एक समाधान (अपना काम समाप्त हो गया है एक काम है कि उपभोक्ता के बाद भेजा है के माध्यम से) एक मास्टर कि n निर्माता कार्यों प्रेषण और प्रत्येक उपभोक्ता मास्टर को सूचित करना होगा है कि यह समाप्त हो गया है, इस मामले में मास्टर एक और निर्माता कार्य भेज देगा। वैकल्पिक रूप से, उपभोक्ता स्वयं पूरा होने पर निर्माता कार्य भेज सकता है।

विशेष रूप से आइटम आप को सुलझा लिया है का जवाब दे:

निर्माता-उपभोक्त समस्या भी घिरा-बफर समस्या के रूप में जाना जाता है, फिर भी ऊपर एक बफर

ए का कोई जिक्र नहीं है साझा बफर की आवश्यकता नहीं है क्योंकि उपभोक्ता उद्देश्य-सी ब्लॉक हैं, जो संदर्भित डेटा को स्वचालित रूप से कैप्चर करते हैं।

अपनी बाध्य

GCD मौजूदा प्रणाली लोड के अनुसार भेजा कार्यों की संख्या सीमा।

या उपभोक्ता

उपभोक्ताओं कार्यों GCD कतारों के लिए भेजा है।

क्रम में निर्माता & उपभोक्ता को अवरुद्ध से अधिक से बचने के लिए/के अधीन ही कार्य

अवरुद्ध कोई साझा किए गए बफर वहाँ के बाद से के लिए कोई ज़रूरत नहीं है अकेले। चूंकि प्रत्येक उपभोक्ता उद्देश्य-सी ब्लॉक संदर्भ कैप्चरिंग तंत्र के माध्यम से उत्पादित डेटा को कैप्चर करने वाला एक उद्देश्य-सी ब्लॉक है, उपभोक्ता और डेटा के बीच एक-से-एक संबंध है।

+1

वाह, यह बहुत अच्छा है। मुझे इसके बारे में सोचना है। धन्यवाद! –

+2

ठीक है, अब मैं इसे प्राप्त करता हूं। यह गियर का मानसिक परिवर्तन है जो चीजों को सरल बनाता है। मैं अपारदर्शी कतार के बारे में थोड़ा डर रहा हूं, हालांकि मैं देखता हूं कि मैं लगभग हर चीज कर सकता हूं जो कि मैं पहले कर सकता था, सिवाय इसके कि अधूरा उपभोक्ता कार्यों को छोड़ दें। मैं इसे नए कोड में उपयोग करूंगा, लेकिन जिस समस्या के लिए मुझे दिमाग था, मैं नहीं कर सकता क्योंकि मेरा उपभोक्ता वास्तविक धागे पर निर्धारित है। शानदार जवाब के लिए धन्यवाद, बहुत बुरा आप डॉको नहीं लिख रहे हैं। –

+0

मुझे इस समाधान के बारे में क्या पसंद नहीं है यह है कि निर्माता निर्णय लेता है कि उपभोक्ता डेटा का उपभोग कैसे करता है (इसे ब्लॉक निर्दिष्ट करना है)। जबकि मैं चाहता हूं कि उपभोक्ता कोड में विभिन्न स्थानों से डेटा का उपभोग करने में सक्षम हो, इस पर निर्भर करता है कि यह किस चरण में प्रसंस्करण के चरण में है। – user102008