मुझे लगता है कि यह खराब अमूर्तता के साथ ही खराब encapsulation है। एक mutex
आमतौर पर कॉपी कन्स्ट्रक्टर के साथ डिफॉल्ट बनाया गया है, जिसमें कई म्यूटेक्स ऑब्जेक्ट्स हैं जो एक ही लॉजिकल ऑब्जेक्ट को संदर्भित करते हैं, त्रुटि प्रवण होता है, यानी यह डेडलॉक्स और अन्य रेस स्थितियों का कारण बन सकता है क्योंकि प्रोग्रामर या पाठक यह मान सकते हैं कि वे अलग-अलग इकाइयां हैं।
इसके अलावा यह निर्दिष्ट करके कि आप किस आंतरिक म्यूटेक्स का उपयोग कर रहे हैं, आप अपने धागे के कार्यान्वयन विवरण को उजागर करेंगे जिससे म्यूटेक्स वर्ग का अमूर्त टूट जाएगा। यदि आप pthread_mutex_t
का उपयोग कर रहे हैं तो आप सबसे अधिक संभावना है कि कर्नेल थ्रेड (pthreads) का उपयोग करें।
Encapsulation भी टूटा हुआ है क्योंकि आपकी म्यूटेक्स एक एकल encapsulated इकाई नहीं है बल्कि कई (संभवतः लटकते) संदर्भों में बिखरी हुई है।
आप इसे क्या करना होगा आप किसी कक्षा के एक pthread_mutex_t
संपुटित चाहते हैं बल्कि यह स्थानीय स्तर पर की घोषणा की और की तुलना में के रूप में तो
class Mutex {
public:
void lock();
void unlock();
// Default and move constructors are good!
// You can store a mutex in STL containers with these
Mutex();
Mutex(Mutex&&);
~Mutex();
// These can lead to deadlocks!
Mutex(const Mutex&) = delete;
Mutex& operator= (const Mutex&) = delete;
Mutex& operator= (Mutex&&) = delete;
private:
pthread_mutex_t internal_mutex;
};
Mutex वस्तुओं एक साझा गुंजाइश कार्यान्वयन फाइलों में घोषित में साझा करने के लिए कर रहे हैं एक संदर्भ के रूप में कार्यों में चारों ओर पारित किया। आप आदर्श रूप से थ्रेड कन्स्ट्रक्टर को केवल तर्कों में ही पारित करेंगे जो आपको चाहिए। प्रश्न में कार्य (इस मामले में थ्रेड निष्पादन) के रूप में एक ही "स्तर" पर एक दायरे में घोषित वस्तुओं के संदर्भ में ऑब्जेक्ट्स के संदर्भों को पास करना आम तौर पर कोड में त्रुटियों का कारण बनता है। क्या होता है यदि म्यूटेक्स घोषित किया गया गुंजाइश अब मौजूद नहीं है? क्या mutex
के विनाशक म्यूटेक्स के आंतरिक कार्यान्वयन को अमान्य कर देगा? क्या होता है यदि म्यूटेक्स चारों ओर पारित होने के माध्यम से पूरे मॉड्यूल के लिए अपना रास्ता बनाता है और वह मॉड्यूल अपने स्वयं के धागे शुरू करता है और सोचता है कि म्यूटेक्स कभी भी अवरुद्ध नहीं होगा, इससे बुरा डेडलॉक्स हो सकता है।
यह भी एक मामला जहां आप म्यूटेक्स चालक का उपयोग करना चाहते हैं, एक म्यूटेक्स फैक्ट्री पैटर्न में कहता है, यदि आप एक नया म्यूटेक्स बनाना चाहते हैं तो आप एक फंक्शन कॉल करेंगे और वह फ़ंक्शन एक म्यूटेक्स वापस करेगा जो आप करेंगे अपने म्यूटेक्स के खो गए या किसी थ्रेड को पास करें जो इसे किसी प्रकार के साझा डेटा के माध्यम से अनुरोध कर रहा है (उपर्युक्त सूची इस साझा डेटा के लिए एक अच्छा विचार होगा)।ऐसे म्यूटेक्स फैक्ट्री पैटर्न को प्राप्त करना हालांकि मुश्किल हो सकता है क्योंकि आपको म्यूटेक्स की सामान्य सूची तक पहुंच को लॉक करने की आवश्यकता है। कोशिश करने के लिए यह एक मजेदार बात होनी चाहिए!
यदि लेखक का इरादा वैश्विक दायरे से बचने के लिए था तो इसे एक स्थिर वस्तु के रूप में कार्यान्वयन फ़ाइल में एक बार घोषित करना पर्याप्त अमूर्त होना चाहिए।
ठीक है, आमतौर पर आप म्यूटेक्स का उपयोग बेहद सावधानीपूर्वक तरीके से करते हैं। जब आप एक म्यूटेक्स को लॉक करते हैं, तो आप लॉक को बहुत छोटी और ध्यान से चुनी गई अवधि के लिए चाहते हैं ताकि आप डेडलॉक न करें। लॉक के संदर्भ को पास करना एक बुरा विचार है - आप लॉक का उपयोग नहीं करते हैं, आप केवल अधिग्रहण करते हैं और फिर आप इसे वापस देते हैं। इसे चारों ओर स्थानांतरित करना (महत्वपूर्ण) संसाधन के उपयोग को ट्रैक करना मुश्किल बनाता है। लॉक के बजाए एक म्यूटेक्स वैरिएबल का संदर्भ पास करना शायद इतना बुरा नहीं है, लेकिन फिर भी यह जानना मुश्किल हो जाता है कि प्रोग्राम के कौन से हिस्से डेडलॉक हो सकते हैं, इसलिए इससे बचने के लिए कुछ है। आमतौर पर आपको इसे करने की ज़रूरत नहीं होती है। –
यदि आप विशेष रूप से अपने mutex wrapper वर्ग में "pthread_mutex &" गुजर रहे हैं, तो मेरा मतलब है कि यह बदसूरत है ... एक के लिए, यदि आप सावधान नहीं हैं, तो आप एक खतरनाक संदर्भ प्राप्त कर सकते हैं, और दो के लिए, आप फिर बंधे हैं pthread कार्यान्वयन के लिए। संभावित रूप से आपकी कक्षा का बिंदु कार्यान्वयन विवरण को कवर करना है, लेकिन यहां आप उन्हें तेजी से लीक कर रहे हैं! –
@ChrisBeck आपके समझाए जाने के प्रयास के लिए धन्यवाद। मैं आपको "उत्तर" में समस्या और उसके समाधान को संबोधित करने का अनुरोध करता हूं। –