2017-10-29 16 views
9

स्थिति चर होना चाहिए notify() और unlock_sleep() के संबंध में एक भी आदेश दिया है। मनमाने ढंग से lockables साथ इस लक्ष्य को पूरा std::condition_variable_any कार्यान्वयन आम तौर पर आंतरिक रूप से एक और म्युटेक्स का उपयोग करें (atomicity सुनिश्चित करने के लिए और पर सोने के लिए)libC++ एसटीडी के कार्यान्वयन :: condition_variable_any

तो आंतरिक unlock_sleep() और notify() (notify_one() या notify_all()) के संचालन के लिए एक दूसरे आप एक धागा जोखिम के संबंध में परमाणु नहीं हैं म्यूटेक्स को अनलॉक करना, एक और थ्रेड सिग्नलिंग और फिर मूल धागा सोना और कभी जागना नहीं।

मैं libstdC++ और libC++ std :: condition_variable_any के कार्यान्वयन को पढ़ने और पाया है this code in the libc++ implementation

{lock_guard<mutex> __lx(*__mut_);} 
__cv_.notify_one(); 

आंतरिक म्युटेक्स लॉक किया गया है और फिर तुरंत संकेत ऑपरेशन से पहले अनलॉक कर दिया गया था। क्या यह ऊपर वर्णित समस्या का जोखिम नहीं उठाता है?

libstdc++ seems to have gotten this right

+0

मैं 'unlock_sleep()' से अपरिचित हूं। क्या आप दस्तावेज़ों के लिए एक लिंक प्रदान कर सकते हैं? साथ ही, 'सूचित करें() 'क्या आपका मतलब' notify_one() 'या' notify_all() 'है? –

+1

@ माइकलबुरर क्षमा करें मेरा मतलब है कि सोने पर जाने और म्यूटेक्स को एक परमाणु ऑपरेशन के रूप में अनलॉक करने का सामान्य संचालन था। मैं – Curious

उत्तर

1

सी ++ 11 और बाद में मानकों को स्पष्ट रूप से कहते हैं कि "notify_one और notify_all के निष्पादन के परमाणु बना रहेगा"। तो एक मायने में मुझे लगता है कि आप सही हैं कि आंतरिक म्यूटेक्स को कॉलम के नीचे प्लेटफॉर्म के अंतर्निहित कंडीशन वेरिएबल नोटिफ़ कॉल (उदाहरण के लिए pthread_cond_signal())

हालांकि, मुझे नहीं लगता कि libC++ कार्यान्वयन होगा अधिसूचनाओं को याद करने के कारण क्योंकि लॉक पर सिंक्रनाइज़िंग थ्रेड को सूचित किए बिना प्रतीक्षा थ्रेड wait() (या दो धागे के बीच कुछ अन्य सिंक्रनाइज़ेशन) तक notify_one() (या notify_all()) पर कॉल करते समय यह सुनिश्चित करने का कोई तरीका नहीं है कि दो धागे कौन से हैं ' पहले 'सूचित करने या वैसे भी इंतजार करने के लिए। इसलिए यदि libC++ के मौजूदा कार्यान्वयन में अधिसूचना को याद किया जा सकता है, तो यह भी याद किया जा सकता है कि libC++ को प्लेटफ़ॉर्म की अधिसूचना API पर कॉल के भीतर आंतरिक लॉक को बदलने के लिए बदला गया था।

तो मैं libC++ आह्वान कर सकते हैं "के रूप में यदि" कहना है कि शासन notify_one()/notify_any() के कार्यान्वयन "पर्याप्त परमाणु" है कि लगता है।

+0

प्रश्न को अपडेट करूँगा> "यदि libC++ के मौजूदा कार्यान्वयन में अधिसूचना को याद किया जा सकता है, तो यह भी याद किया जा सकता है कि libC++ को प्लेटफ़ॉर्म की अधिसूचना API पर कॉल करने के लिए आंतरिक लॉक को बदलने के लिए बदला गया था" मुझे ऐसा नहीं लगता , अगर आंतरिक ताला आयोजित किया गया था। फिर आंतरिक म्यूटेक्स को सोने और अनलॉक करने का पूरा अनुक्रम परमाणु होगा। यदि आंतरिक ताला लगाया गया तो आंतरिक म्यूटेक्स को अनलॉक करने और सोने जाने के बीच में सही तरीके से रेंगने के लिए कोई रास्ता नहीं होगा (जो समस्या मैं पूछ रहा हूं) – Curious

+0

ये दो परिदृश्य अलग-अलग कैसे हैं: * * परिदृश्य 1) ​​** थ्रेड डब्ल्यू की 'प्रतीक्षा()' आंतरिक म्यूटेक्स प्राप्त करता है तो थ्रेड एन की 'notify_one() 'होती है (क्योंकि यह पहले से ही आंतरिक म्यूटेक्स जारी कर चुका है) थ्रेड डब्ल्यू वास्तव में' pthread_cond_wait()' पर कॉल करता है, और ** परिदृश्य 2) ** धागा एन 'notify_one()' कॉल पूरी तरह से थ्रेड डब्ल्यू 'प्रतीक्षा()' कॉल आंतरिक म्यूटेक्स प्राप्त करने से ठीक पहले निष्पादित करता है? मेरा मानना ​​है कि कुछ बाहरी सिंक्रनाइज़ेशन के बिना एपीआई का उपयोगकर्ता उन दो स्थितियों के बीच अंतर नहीं कर सकता है। –

+0

फिर 'notify_one() 'में पहली जगह में म्यूटक्स क्यों प्राप्त करें? – Curious

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