2016-10-07 5 views
6

मैं सोच रहा था क्या इस तरह के एक वर्ग में क्या होगा:एक बहुप्रचारित वातावरण में विनाशक?

class MyClass 
{ 
private: 
    std::vector<int> iVector; 
    void Worker() 
    { 
     //Lots of stuff done with iVector 
     //adding, removing elements, etc. 
    } 
} 

चलो कहते हैं कि मैं एक धागा (वर्ग के सदस्य कार्यों में से एक द्वारा लाया) iVector उपयोग करता है और उसे संशोधित करता है कि बनाएँ। इस कार्यकर्ता के अलावा, कक्षा के अन्य सदस्य कार्य इस std :: वेक्टर को पढ़ या संशोधित नहीं करते हैं।

सबकुछ ठीक लगता है क्योंकि वर्कर थ्रेड iVector का उपयोग करने वाला एकमात्र है।

लेकिन क्या होगा जब वस्तु का एक उदाहरण नष्ट हो जाए? यहां तक ​​कि यदि कार्यकर्ता धागा समाप्त होने के बाद वस्तु नष्ट हो जाती है, तो iVector के लिए विनाशक मुख्य धागे से आवेदक लगाया जाएगा। क्या इससे अपरिभाषित व्यवहार होगा?

धन्यवाद!

+0

यदि ऑब्जेक्ट का जीवनकाल थ्रेड या ऑब्जेक्ट के किसी भी अन्य उपयोग से लंबा है, तो कोई यूबी नहीं है। –

+2

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

+0

ऑब्जेक्ट का जीवनकाल अब धागे से नहीं है। लेकिन थ्रेड ए में वेक्टर को नष्ट करना ठीक क्यों है जब इसे थ्रेड बी (वर्कर थ्रेड) में संशोधित किया जाता है? – sapito

उत्तर

3

सबसे पहले मैं विनाशक में धागे पर std::join (या आपकी लाइब्रेरी समकक्ष) चलाने का सुझाव दूंगा। यह सुनिश्चित करेगा कि थ्रेड ठीक से समाप्त हो गया है और वेक्टर विनाशक चलाने से पहले सिंक्रनाइज़ किया गया है। यह महत्वपूर्ण है क्योंकि वेक्टर के जीवनकाल का उपयोग करके धागे से अधिक होना चाहिए।

सी ++ 11 मानक और शायद बाद में 30.3.1.5 में लोगों को राज्य:

5: तुल्यकालन: धागा द्वारा * इस के साथ सिंक्रनाइज़ का प्रतिनिधित्व के पूरा होने (1.10) इसी सफल में शामिल होने के () वापसी। [ नोट: * पर ऑपरेशंस सिंक्रनाइज़ नहीं हैं। - अंत टिप्पणी]

अब हम, और अधिक विस्तार के लिए 1.10 की जांच करने के लिए है पहले इस खंड कहता है:

3: एक खास बिंदु पर एक वस्तु एक धागा टी के लिए दिखाई दे का मूल्य है ऑब्जेक्ट का प्रारंभिक मान, टी द्वारा ऑब्जेक्ट को आवंटित मान, या के अनुसार नीचे दिए गए नियमों के अनुसार, किसी अन्य थ्रेड द्वारा ऑब्जेक्ट को आवंटित मान।

ईमानदारी से, यह पार्स करने के लिए मुश्किल है, यह वास्तव में क्या तुल्यकालन की तरह प्रदान करता है में शामिल होने को निर्दिष्ट नहीं करता और यह केवल धागा ही है और न डेटा यह तक पहुंचा था सिंक्रनाइज़ करता है मतलब है लगता है। इसलिए मैं सुरक्षित मार्ग पर जाऊंगा और मुख्य धागे में शामिल होने के बाद atomic_thread_fence(memory_order_acquire) चला सकता हूं, और atomic_thread_fence(memory_order_release) बच्चे के धागे में खत्म होने से ठीक पहले, जो पूर्ण होना चाहिए, अर्थात् सेमेन्टिक्स से पहले और कोई यूबी नहीं होता है।

+0

को नष्ट करने से पहले कार्यकर्ता थ्रेड सभी शामिल हो गए हैं, मैं पहले से ही stCl :: को MyClass के विनाशक में थ्रेड पर शामिल कर रहा हूं। लेकिन मुझे नहीं पता था कि std :: join कॉलिंग थ्रेड को वर्किंग थ्रेड में लापता होने से रोकता है :) – sapito

+0

@sapito मुझे अपने सी ++ मानक को तुरंत पढ़ने दें और फिर मैं देखूंगा कि यह निश्चित रूप से सुरक्षित है – Vality

+0

@sapito मैंने अपना जवाब अपडेट किया है कुछ मानक उद्धरण और अतिरिक्त सुरक्षा प्राप्त करने की एक विधि के साथ यदि आप अकेले शामिल होने पर आत्मविश्वास नहीं रखते हैं तो पर्याप्त है। ईमानदारी से मैं मानक से पार्स नहीं कर सकता अगर केवल धागे को समाप्त करने के सिंक्रनाइज़ करता है, या डेटा थ्रेड का उपयोग कर रहा था। न ही यह कहता है कि यह किस तरह का सिंक्रनाइज़ेशन अर्थशास्त्र प्रदान करता है .. इसलिए सुरक्षित होने के लिए आप बाड़ मार्ग का उपयोग कर सकते हैं। – Vality

2

यदि कोई निष्पादन थ्रेड ivector वर्ग सदस्य का उपयोग कर रहा है, और दूसरा धागा इस वर्ग के सदस्य के साथ ऑब्जेक्ट को नष्ट कर देता है, तो ivector वर्ग सदस्य का निरंतर उपयोग अपरिभाषित व्यवहार में होता है।

यहां तक ​​कि अगर वस्तु के बाद कार्यकर्ता धागा समाप्त हो गया है नष्ट हो जाता है, iVector के लिए नाशक मुख्य थ्रेड से लागू किया जाएगा। यह अनिश्चित व्यवहार के लिए नेतृत्व करेंगे?

नहीं। जैसा कि आपने वर्णन किया है, यह स्थिति अपरिभाषित व्यवहार नहीं है। सी ++ मानक को किसी वस्तु को उसी निष्पादन थ्रेड द्वारा नष्ट करने की आवश्यकता नहीं होती है जिसने ऑब्जेक्ट बनाया है।एक निष्पादन धागा बढ़ने के लिए ठीक है, वेक्टर का आकार बदलें, फिर वेक्टर का उपयोग करके दूर या बंद करें, और फिर एक अलग निष्पादन धागा पूरे ऑब्जेक्ट को नष्ट कर देता है।

+0

यहां तक ​​कि यदि यह मेरे मूल प्रश्न का हिस्सा नहीं है, तो यह जानना अच्छा होगा कि विनाशक को अन्य थ्रेड (सदस्य फ़ंक्शन के विपरीत) के परिवर्तनों के साथ सिंक्रनाइज़ किया जाता है। बीटीडब्ल्यू, मैं किस बारे में बात कर रहा हूं: थ्रेड ए std :: वेक्टर बनाता है और नष्ट करता है (लेकिन इसे कभी संशोधित या पढ़ता नहीं है), थ्रेड बी संशोधित करता है और इसे पढ़ता है। – sapito

+0

यह "सिंक्रनाइज़ेशन" विनाशक का आह्वान करने के कार्य से संबंधित नहीं है। सी ++ मानक में एक संपूर्ण उबाऊ, लंबा अनुभाग होता है जो "अनुक्रमण" के लिए औपचारिक विनिर्देश को बाहर करता है, यह तब होता है जब एक निष्पादित थ्रेड में सभी "परिवर्तन" किसी अन्य थ्रेड में दिखाई देते हैं। किसी ऑब्जेक्ट को नष्ट करना इस तरह से अनुक्रमित किया जाना चाहिए कि अन्य धागे से ऑब्जेक्ट के सभी संदर्भों को पहले से ही ऑब्जेक्ट को नष्ट करने वाले थ्रेड से पहले अनुक्रमित किया जाना चाहिए। यह ठीक से अनुक्रमित करने के लिए बहुप्रचारित कोड पर निर्भर है। एक वस्तु का विनाशक इसके लिए ज़िम्मेदार नहीं है। –

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