मुझे लगता है कि सुनने के const
साधन धागा सुरक्षित में सी ++ 11 । क्या यह सच है?
यह कुछ हद तक है सही है ...
यह क्या है मानक भाषा धागे की सुरक्षा पर क्या कहना है:
[१.१० / ४]
दो अभिव्यक्ति मूल्यांकन संघर्ष अगर उनमें से एक मेमोरी लोकेशन (१.)) को संशोधित करता है और दूसरा एक ही मेमोरी लोकेशन को एक्सेस या संशोधित करता है।
[१.१० / २१]
एक कार्यक्रम के निष्पादन में एक डेटा रेस होती है, यदि इसमें विभिन्न थ्रेड्स में दो परस्पर विरोधी क्रियाएं होती हैं, जिनमें से कम से कम एक परमाणु नहीं है, और न ही दूसरे से पहले होता है। ऐसी किसी भी डेटा दौड़ के परिणाम अपरिभाषित व्यवहार में होते हैं।
डेटा रेस होने के लिए पर्याप्त स्थिति के अलावा और कुछ नहीं है:
- किसी दिए गए चीज़ पर एक ही समय में दो या अधिक क्रियाएं की जा रही हैं; तथा
- कम से कम उनमें से एक लेखन है।
स्टैंडर्ड लाइब्रेरी उस पर बनाता है, थोड़ा आगे जाने:
[१ [.६.५.९ / १]
यह खंड उन आवश्यकताओं को निर्दिष्ट करता है जो क्रियान्वयन डेटा दौड़ (१.१०) को रोकने के लिए पूरा होगा। प्रत्येक मानक पुस्तकालय समारोह प्रत्येक आवश्यकता को पूरा करेगा जब तक कि अन्यथा निर्दिष्ट न हो। कार्यान्वयन नीचे निर्दिष्ट लोगों के अलावा अन्य मामलों में डेटा दौड़ को रोक सकता है।
[१ [.६.५.९ / ३]
एक सी ++ मानक पुस्तकालय फ़ंक्शन प्रत्यक्ष या अप्रत्यक्ष रूप से वस्तुओं को (१.१०) वर्तमान धागे के अलावा अन्य थ्रेड द्वारा सुलभ नहीं करेगा, जब तक कि ऑब्जेक्ट सीधे या अप्रत्यक्ष रूप से फ़ंक्शन के नॉन- कॉस्ट तर्कोंके माध्यम से एक्सेस न होंthis
।
जो सरल शब्दों में कहता है कि यह अपेक्षा करता है कि const
वस्तुओं पर संचालन थ्रेड-सुरक्षित होगा । इसका मतलब यह है कि मानक लाइब्रेरी तब तक डेटा रेस की शुरुआत नहीं करेगी, जब तक कि const
आपके अपने प्रकार की वस्तुओं पर कार्रवाई नहीं होती है
- पूरी तरह से पढ़ता है - यह है, वहाँ कोई लिख रहे हैं -; या
- आंतरिक रूप से लिखता है।
यदि यह अपेक्षा आपके किसी एक प्रकार के लिए नहीं है, तो मानक पुस्तकालय के किसी भी घटक के साथ प्रत्यक्ष या अप्रत्यक्ष रूप से इसका उपयोग करने से डेटा रेस हो सकती है । अंत में, मानक पुस्तकालय बिंदु से थ्रेड-सेफ काconst
मतलब है । यह ध्यान रखना महत्वपूर्ण है कि यह केवल एक अनुबंध है और इसे कंपाइलर द्वारा लागू नहीं किया जाएगा, यदि आप इसे तोड़ते हैं तो आपको अपरिभाषित व्यवहार मिलता है और आप अपने दम पर होते हैं। चाहे मौजूद है या कम से कम --at के संबंध में नहीं कोड पीढ़ी नहीं कोई असर नहीं पड़ेगा डेटा दौड़ -।const
इसका मतलब यह है const
है अब के बराबर जावा के synchronized
?
नहीं । हर्गिज नहीं...
आयत का प्रतिनिधित्व करने वाले निम्न सरलीकृत वर्ग पर विचार करें:
class rect {
int width = 0, height = 0;
public:
/*...*/
void set_size( int new_width, int new_height ) {
width = new_width;
height = new_height;
}
int area() const {
return width * height;
}
};
सदस्य-समारोह area
है धागा सुरक्षित ; इसकी वजह से नहीं const
, बल्कि इसलिए कि इसमें पूरी तरह से रीड ऑपरेशन शामिल हैं। इसमें कोई लेखन शामिल नहीं है, और डेटा दौड़ होने के लिए कम से कम एक लेखन शामिल होना आवश्यक है। इसका मतलब है कि आप कॉल कर सकते हैंarea
जितने चाहें उतने धागे से हैं और आपको हर समय सही परिणाम मिलेंगे।
ध्यान दें कि यह है कि इसका मतलब यह नहीं rect
है धागा सुरक्षित । वास्तव में, यह देखना आसान है कि कैसे कॉल एक area
ही समय में होने वाली थी कि set_size
किसी दिए गए कॉल पर rect
, फिरarea
पुरानी चौड़ाई और नई ऊंचाई (या यहां तक कि विकृत मूल्यों पर आधारित) के आधार पर इसके परिणाम की गणना कर सकता है। ।
लेकिन यह है कि ठीक, rect
नहीं है const
तो इसकी भी होने के लिए नहीं की उम्मीद धागा सुरक्षित सब के बाद। const rect
दूसरी ओर, घोषित की गई कोई वस्तु तब तक सुरक्षित रहेगी, जब तक कि कोई भी लेखन संभव नहीं है (और यदि आप const_cast
मूल रूप से घोषित की गई किसी चीज़ पर विचार कर रहे हैं, const
तो आप अपरिभाषित व्यवहार प्राप्त करते हैं और ऐसा ही है)।
तो फिर इसका क्या मतलब है?
चलिए मान लेते हैं - तर्क की खातिर-- कि गुणन ऑपरेशन बेहद खर्चीले हैं और जब संभव हो तो हम बेहतर तरीके से उनसे बचते हैं। यदि अनुरोध किया जाता है, तो हम इस क्षेत्र की गणना कर सकते हैं और भविष्य में फिर से अनुरोध किए जाने पर इसे कैश कर सकते हैं:
class rect {
int width = 0, height = 0;
mutable int cached_area = 0;
mutable bool cached_area_valid = true;
public:
/*...*/
void set_size( int new_width, int new_height ) {
cached_area_valid = ( width == new_width && height == new_height );
width = new_width;
height = new_height;
}
int area() const {
if( !cached_area_valid ) {
cached_area = width;
cached_area *= height;
cached_area_valid = true;
}
return cached_area;
}
};
[यदि यह उदाहरण बहुत अधिक कृत्रिम लगता है, तो आप मानसिक रूप int
से एक बहुत ही गतिशील रूप से आवंटित पूर्णांक द्वारा प्रतिस्थापित कर सकते हैं जो स्वाभाविक रूप से गैर थ्रेड-सुरक्षित है और जिसके लिए गुणन बहुत महंगा है।]
सदस्य-समारोह area
नहीं रह गया है धागे की सुरक्षित यह अब राईट कर रही है और आंतरिक रूप से संबद्ध नहीं है,। कोई समस्या है? कॉल किसी अन्य ऑब्जेक्ट के कॉपी-कंस्ट्रक्टर के area
हिस्से के रूप में हो सकता है , इस तरह के कंस्ट्रक्टर को एक मानक कंटेनर पर कुछ ऑपरेशन द्वारा बुलाया जा सकता था , और उस समय मानक लाइब्रेरी को उम्मीद है कि यह ऑपरेशन डेटा रेस के संबंध में रीड के रूप में व्यवहार करेगा। । लेकिन हम लिख रहे हैं!
जैसे ही हम rect
एक मानक कंटेनर में डालते हैं - प्रत्यक्ष या अप्रत्यक्ष रूप से - हम मानक पुस्तकालय के साथ एक अनुबंध में प्रवेश कर रहे हैं । उस अनुबंध का सम्मान करते हुए भी एक फ़ंक्शन में लिखते रहना , हमें उन लेखों को आंतरिक रूप से सिंक्रनाइज़ करना होगा:const
class rect {
int width = 0, height = 0;
mutable std::mutex cache_mutex;
mutable int cached_area = 0;
mutable bool cached_area_valid = true;
public:
/*...*/
void set_size( int new_width, int new_height ) {
if( new_width != width || new_height != height )
{
std::lock_guard< std::mutex > guard( cache_mutex );
cached_area_valid = false;
}
width = new_width;
height = new_height;
}
int area() const {
std::lock_guard< std::mutex > guard( cache_mutex );
if( !cached_area_valid ) {
cached_area = width;
cached_area *= height;
cached_area_valid = true;
}
return cached_area;
}
};
ध्यान दें कि हमने area
फ़ंक्शन को थ्रेड-सुरक्षित बनाया है , लेकिन फिर rect
भी थ्रेड-सुरक्षित नहीं है । एक कॉल area
उसी समय हो रहा है कि एक कॉल set_size
अभी भी गलत मान की गणना कर सकती है, क्योंकि असाइनमेंट म्यूटेक्स द्वारा संरक्षित width
और height
संरक्षित नहीं हैं।
अगर हम वास्तव में एक धागा-तिजोरी चाहते थे rect
, तो हम नॉन-थ्रेड-सेफ़ की सुरक्षा के लिए एक सिंक्रोनाइज़ेशन प्रिमिटिव का उपयोग करेंगे rect
।
क्या वे बाहर भाग रहे हैं? कीवर्ड से?
हाँ वे हैं। वे बाहर भागते रहे हैं दिन से ही कीवर्ड से हैं।
स्रोत : आप नहीं जानते const
औरmutable
- हर्ब सटर