हर्ब का जवाब (इससे पहले कि इसे संपादित किया गया था) वास्तव में एक प्रकार का एक अच्छा उदाहरण देता है जो जंगम नहीं होना चाहिएstd::mutex
:।
OS का मूल म्यूटेक्स प्रकार (जैसे pthread_mutex_t
POSIX प्लेटफ़ॉर्म पर) "स्थान अपरिवर्तनीय" नहीं हो सकता है जिसका अर्थ है कि वस्तु का पता उसके मूल्य का हिस्सा है। उदाहरण के लिए, OS सभी आरंभिक म्यूटेक्स ऑब्जेक्ट की ओर संकेत कर सकता है। यदि std::mutex
डेटा सदस्य के रूप में एक मूल OS म्यूटेक्स प्रकार समाहित है और मूल प्रकार का पता निश्चित रहना चाहिए (क्योंकि OS अपने म्यूटेक्स की ओर संकेत करता है) तो या तो std::mutex
मूल mutex प्रकार को ढेर पर संग्रहीत करना होगा, जिस पर वह रुकेगा std::mutex
वस्तुओं के बीच स्थानांतरित होने पर या std::mutex
स्थानांतरित नहीं होना चाहिए। ढेर पर यह भंडारण संभव है क्योंकि एक नहीं है, std::mutex
एक है constexpr
निर्माता और निरंतर प्रारंभ (यानी स्थिर आरंभीकरण) तो एक वैश्विक कि लिए योग्य होना चाहिएstd::mutex
कार्यक्रम के निष्पादन शुरू होने से पहले निर्माण करने की गारंटी है, इसलिए इसका निर्माणकर्ता उपयोग नहीं कर सकता है new
। इसलिए बचा एकमात्र विकल्प std::mutex
अचल होने के लिए है।
एक ही तर्क अन्य प्रकारों पर लागू होता है जिसमें कुछ ऐसा होता है जिसे एक निश्चित पते की आवश्यकता होती है। यदि संसाधन का पता निश्चित रहना चाहिए, तो उसे स्थानांतरित न करें!
आगे बढ़ने के लिए एक और तर्क std::mutex
है जो यह है कि इसे सुरक्षित रूप से करना बहुत कठिन होगा, क्योंकि आपको यह जानना होगा कि कोई भी उस समय म्यूटेक्स को लॉक करने की कोशिश नहीं कर रहा है जो इसे स्थानांतरित किया जा रहा है। चूंकि म्यूटेक्स बिल्डिंग ब्लॉकों में से एक है, जिसका उपयोग आप डेटा रेस को रोकने के लिए कर सकते हैं, यह दुर्भाग्यपूर्ण होगा यदि वे स्वयं रेस के लिए सुरक्षित नहीं थे! अचल होने के साथ std::mutex
ही आप जानते हैं कि एक बार निर्माण होने के बाद ही कोई भी ऐसा कर सकता है और नष्ट होने से पहले इसे लॉक करना और इसे अनलॉक करना है, और उन ऑपरेशनों को स्पष्ट रूप से थ्रेड सुरक्षित होने और डेटा दौड़ शुरू नहीं करने की गारंटी है। यही तर्क std::atomic<T>
वस्तुओं पर लागू होता है : जब तक कि उन्हें परमाणु रूप से स्थानांतरित नहीं किया जा सकता है तब तक उन्हें सुरक्षित रूप से स्थानांतरित करना संभव नहीं होगा, एक और धागा कॉल करने की कोशिश कर सकता हैcompare_exchange_strong
इस समय वस्तु को दाईं ओर ले जाया जा रहा है। तो एक और मामला जहां प्रकार नहीं होने चाहिए, वह वह है जहां वे सुरक्षित समवर्ती कोड के निम्न-स्तर के निर्माण खंड हैं और उन पर सभी कार्यों की परमाणुता सुनिश्चित करनी चाहिए। यदि किसी भी समय वस्तु के मूल्य को एक नई वस्तु में ले जाया जा सकता है, तो आपको प्रत्येक परमाणु चर की रक्षा के लिए एक परमाणु चर का उपयोग करने की आवश्यकता होगी, ताकि आप जान सकें कि क्या इसका उपयोग करना सुरक्षित है या इसे स्थानांतरित कर दिया गया है ... और रक्षा करने के लिए एक परमाणु चर उस परमाणु चर, और इतने पर ...
मुझे लगता है कि मैं यह कहना सामान्य करूंगा कि जब कोई वस्तु सिर्फ स्मृति का एक शुद्ध टुकड़ा है, न कि एक प्रकार जो मूल्य के लिए धारक के रूप में कार्य करता है या मूल्य के अमूर्त होने पर, इसे स्थानांतरित करने का कोई मतलब नहीं है। मौलिक प्रकार जैसे कि int
स्थानांतरित नहीं किया जा सकता है: उन्हें स्थानांतरित करना सिर्फ एक प्रति है। आप हिम्मत से बाहर चीर नहीं int
कर सकते हैं, आप इसके मूल्य की प्रतिलिपि बना सकते हैं और फिर इसे शून्य पर सेट कर सकते हैं, लेकिन यह अभी भी int
एक मूल्य के साथ है, यह सिर्फ स्मृति के बाइट्स है। लेकिन एक int
अभी भी चल रहा हैभाषा के शब्दों में क्योंकि एक कॉपी एक मान्य चाल ऑपरेशन है। हालांकि, गैर-प्रतिलिपि योग्य प्रकारों के लिए, यदि आप स्मृति के टुकड़े को स्थानांतरित नहीं कर सकते या नहीं कर सकते हैं और आप इसके मूल्य की प्रतिलिपि भी नहीं बना सकते हैं, तो यह गैर-जंगम है। एक म्यूटेक्स या एक परमाणु चर स्मृति का एक विशिष्ट स्थान है (विशेष गुणों के साथ इलाज किया गया) इसलिए इसे स्थानांतरित करने के लिए समझ में नहीं आता है, और यह प्रतिलिपि करने योग्य भी नहीं है, इसलिए यह गैर-जंगम है।