9

मैं के साथ बनाई गई एक सीरियल प्रेषण कतार है कॉलिंग थ्रेड पर लौटें।dispatch_async बनाम dispatch_sync निष्पादन आदेश

- (void)addObjectToQueue:(id)object 
{ 
    dispatch_async(serialQueue, ^{ 
     // process object and add to queue 
    }); 
} 

- (BOOL)isObjectInQueue:(id)object 
{ 
    __block BOOL returnValue = NO; 
    dispatch_sync(serialQueue, ^{ 
     // work out return value 
    }); 
    return returnValue; 
} 

अगर मैं addObjectToQueue फोन: विधि, तो तुरंत isObjectInQueue फोन: विधि, वे उसी क्रम में क्रियान्वित किया जा करने की गारंटी, या/isObjectInQueue पहले निष्पादित कर सकता है कर रहे हैं?

दूसरे शब्दों में, dispatch_async dispatch_sync (तुरंत ब्लॉक को शेड्यूल करना) के समान ही करता है सिवाय इसके कि यह कॉलिंग थ्रेड को अवरुद्ध नहीं करता है?

मैंने दोनों तरीकों से उत्तर के साथ समान प्रश्न देखे हैं, इसलिए मैं एक निश्चित उत्तर की तलाश में हूं, जिसे ऐप्पल दस्तावेज के साथ अधिमानतः समर्थित किया गया है।

+2

"अगर मैं addObjectToQueue: विधि को कॉल करता हूं, तो तुरंत isObjectInQueue: विधि को कॉल करें, क्या वे उसी क्रम में निष्पादित होने की गारंटी देते हैं, या पहले ऑब्जेक्टइन्यूयूयू पहले निष्पादित करेगा?" यह पूछकर आप शायद मतलब "क्या हम कतार में जोड़े जाने से पहले ऑब्जेक्ट के लिए पूछ सकते हैं?"। क्योंकि, जाहिर है, 2 विधियों को क्रम में चलाने के लिए कहा जाता है यदि उन्हें एक ही धागे पर बुलाया जाता है। – krafter

उत्तर

13

क्या वे उसी क्रम में निष्पादित होने की गारंटी देते हैं?

हां।

isObjectInQueue पहले निष्पादित करेगा?

हां।

दोनों उत्तरों के लिए हाँ का कारण आपको थ्रेडिंग पर विचार करना चाहिए। संभवतः आप पहली जगह सीरियल कतार का उपयोग क्यों कर रहे हैं। आप उस कतार धागे को सुरक्षित बना रहे हैं।

असल में, ब्लॉक क्रम में निष्पादित किए जाएंगे जिसमें उन्हें सीरियल कतार पर रखा जाएगा। यह 100% गारंटी है। हालांकि, अगर इस पर कई धागे छेड़छाड़ कर रहे हैं तो एक धागा को पहले कतार से कुछ पढ़ने के लिए मिल सकता है इससे पहले कि किसी को इसे जोड़ने का मौका मिला हो।

दूसरे शब्दों में, सिवाय इसके कि यह बुला धागा ब्लॉक नहीं करता (ब्लॉक तुरंत समय निर्धारण) dispatch_async ठीक उसी dispatch_sync के रूप में प्रदर्शन करता है?

यह सही है। दोनों मामलों में ब्लॉक कतार में जोड़ा जाता है। यह तुरंत जोड़ा जाता है। dispatch_sync बस लौटने से पहले ब्लॉक को समाप्त करने की प्रतीक्षा करता है जबकि dispatch_async तुरंत लौटता है।

+2

दाएं; या, संक्षेप में, एक धारावाहिक कतार पर ब्लॉक को क्रम में निष्पादित किया जाएगा और वह आदेश केवल तभी निर्धारित होगा जब आप एक थ्रेड से 'dispatch_async()/dispatch_sync() ' यदि बहु-थ्रेडेड और आपको ऑर्डर की आवश्यकता है, तो आपको सिंक्रनाइज़ेशन तंत्र प्रदान करना होगा। आपको 'isObjectInQueue: 'के रिटर्न वैल्यू के लिए शायद" ताजगी "संकेतक की आवश्यकता होगी, क्योंकि यह एक समवर्ती वातावरण में तुरंत वैधता खो सकता है। अर्थात। समेकन कठिन है। – bbum

+0

हालांकि यह चर्चा पुरानी है, लेकिन मैं कुछ क्षणों को स्पष्ट करने के लिए इसे पुनर्जीवित करना चाहता हूं। 1. "क्या ऑब्जेक्ट इंक्वाययू पहले निष्पादित करेगा? हाँ।" एंड्रयू पूछता है कि ** METHODS ** एक दूसरे के बाद यादृच्छिक क्रम में चलाया जा सकता है, dispatch_async के अंदर ब्लॉक नहीं। लेकिन: 2. वह शायद खुद को ब्लॉक करता है। :)। लेकिन फिर भी, यदि धारावाहिक कतार पर अंतिम बार जोड़ा गया तो क्या एक ब्लॉक को दूसरे से पहले निष्पादित किया जा सकता है? ** "dispathc_async - प्रेषण कतार पर एसिंक्रोनस निष्पादन के लिए एक ब्लॉक सबमिट करता है और तुरंत लौटाता है। इस फ़ंक्शन पर कॉल हमेशा तत्काल वापस आते हैं _after_ ब्लॉक सबमिट कर दिया गया है।" ** – krafter

2

मुझे लगता है कि आपका प्रश्न है, क्या मुख्य धागा चल रहा है जबकि dispatch_async अभी भी कतार ऑपरेशन निष्पादित कर रहा है? मुझे लगता है कि यह नहीं होगा, क्योंकि यह एक स्पष्ट उल्लेख के लायक होगा। कुछ भी है, मैं dispatch_async.3 में यह पाया जिससे पता चलता है यह मामला है:

वैचारिक रूप से, dispatch_sync() के लिए एक सुविधाजनक आवरण dispatch_async आसपास () एक सेमाफोर के योग के साथ ब्लॉक के पूरा करने के लिए प्रतीक्षा करने के लिए है, और इसके को पूरा करने के लिए ब्लॉक के चारों ओर एक रैपर।

और वास्तव में, यदि आप dispatch_async in queue.c के लिए स्रोत कोड का पालन आपको लगता है कि ब्लॉक अग्रभूमि पर कतारबद्ध है, और केवल उसके बाद, निष्पादन कोड कि dispatch_async बुलाया रिटर्न देखेंगे। इसलिए यदि कतार धारावाहिक है, dispatch_async के बाद dispatch_syncउसी धागे से क्रमशः ब्लॉक को कतारबद्ध करेगा।

क्योंकि dispatch_sync ब्लॉक तक ब्लॉक करेगा (और एक धारावाहिक कतार में पहले सभी ब्लॉक निष्पादित किए जाते हैं), तो आपका कोड सही होगा। isObjectInQueue: सही ढंग से रिपोर्ट करेगा यदि कतार में पहले जोड़ा गया ऑब्जेक्ट है।

संपादित: एक बहु-क्रम पर्यावरण पर मैं के रूप में ऊपर कोड लिखने होगा:

- (void)addObjectToQueue:(id)object 
{ 
    dispatch_barrier_async(_queue, ^{ 
     // process object and add to queue 
    }); 
} 

- (BOOL)isObjectInQueue:(id)object 
{ 
    __block BOOL returnValue = NO; 
    dispatch_sync(_queue, ^{ 
     // work out return value 
    }); 
    return returnValue; 
} 

क्योंकि प्रत्येक विधि के निष्पादन के एक और धागा के पक्ष में किसी भी बिंदु पर आस्थगित जा सकता है।

+0

dispatch_barrier_async प्रलेखन पढ़ने से, यदि आप एक धारावाहिक कतार का उपयोग कर रहे हैं तो खुद को बनाया गया व्यवहार dispatch_async जैसा ही होगा। क्या वो सही है? – Andrew

+0

हां। ऊपर दिया गया कोड बहुसंख्यक वातावरण के लिए एक समवर्ती कतार के उपयोग को मानता है क्योंकि पढ़ना क्रमबद्ध करना एक व्यर्थ रोडब्लॉक होगा। एक सीरियल कतार के साथ, बाधा लागू करने के लिए समवर्ती रूप से निष्पादित करने वाले कोई ब्लॉक नहीं हैं, इसलिए dispatch_barrier_async एक dispatch_async के बराबर है। – Jano

+1

'dispatch_barrier_async()' एक धारावाहिक कतार पर कुछ भी नहीं करता है, क्योंकि परिभाषा के अनुसार, बैरियर वाले ब्लॉक को निष्पादित किए जाने तक सभी पूर्व संलग्न ब्लॉक निष्पादित किए जाएंगे। यह केवल समवर्ती कतारों को प्रभावित करता है। – bbum

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