मैंने कई लेख, वार्ता और स्टैकओवरफ़्लो प्रश्नों के बारे में सुना और पढ़ा है std::atomic
, और मैं यह सुनिश्चित करना चाहूंगा कि मैंने इसे अच्छी तरह से समझा है। क्योंकि मैं अभी भी थोड़ा उलझन में हूं क्योंकि कैश लाइन MESI (या व्युत्पन्न) कैश सुसंगतता प्रोटोकॉल, स्टोर बफ़र्स, अमान्य कतारों, और इतने पर संभावित देरी के कारण दृश्यता लिखती है।
मैंने पढ़ा है कि x86 में एक मजबूत मेमोरी मॉडल है, और अगर कैश अमान्य होने में देरी हो रही है तो x86 परिचालन शुरू कर सकता है। लेकिन मुझे अब केवल उस चीज पर दिलचस्पी है जो मुझे एक सी ++ प्रोग्रामर के रूप में ग्रहण करना चाहिए, स्वतंत्र रूप से प्लेटफॉर्म के रूप में।
[T1: thread1 T2: thread2 V1: साझा परमाणु चर]
मैं समझता हूँ कि std :: परमाणु गारंटी देता है कि,
(1) कोई डेटा दौड़ चर पर नहीं होती (कैश लाइन के लिए विशेष पहुंच के लिए धन्यवाद)।
(२) जिस मेमोरी_ऑर्डर का हम उपयोग करते हैं, उसके आधार पर यह (बाधाओं के साथ) गारंटी देता है कि अनुक्रमिक स्थिरता (एक बाधा से पहले, एक बाधा या दोनों के बाद) होती है।
(3) T1 पर एक परमाणु लेखन (V1) के बाद, T2 पर एक परमाणु RMW (V1) सुसंगत होगा (इसकी कैश लाइन T1 पर लिखित मूल्य के साथ अद्यतन की गई होगी)।
लेकिन कैश सुसंगत प्राइमर के रूप में ,
इन सभी चीजों का निहितार्थ यह है कि, डिफ़ॉल्ट रूप से, लोड हो सकता है बासी डेटा (यदि एक अमान्य अनुरोध अनुरोध अमान्य कतार में बैठा था)
तो, निम्नलिखित सही है?
(4) इस std::atomic
बात की गारंटी नहीं देता है कि T1 पर परमाणु लेखन (V) के बाद T2 किसी परमाणु रीड (V) पर 'बासी' मान नहीं पढ़ेगा।
यदि प्रश्न (4) सही है: यदि T1 पर एटॉमिक राइट कैश लाइन को विलंबित करता है, तो देरी क्यों नहीं होती है, T2 अमान्य आरएमडब्ल्यू ऑपरेशन के लिए प्रभावी होने का इंतजार क्यों कर रहा है, लेकिन परमाणु रीड पर नहीं?
प्रश्न अगर (4) गलत है: जब कोई थ्रेड 'बासी' मान पढ़ सकता है और निष्पादन में "यह दिखाई दे रहा है", तब?
मैं आपके उत्तरों की बहुत सराहना करता हूं
अपडेट १
तो ऐसा लगता है कि मैं (3) पर गलत था। प्रारंभिक V1 = 0 के लिए निम्नलिखित इंटरलेव की कल्पना करें:
T1: W(1)
T2: R(0) M(++) W(1)
भले ही टी 2 का आरएमडब्ल्यू इस मामले में डब्ल्यू (1) के बाद पूरी तरह से होने की गारंटी है, फिर भी यह 'बासी' मूल्य (मैं गलत था) पढ़ सकता हूं। इसके अनुसार, परमाणु पूर्ण कैश सुसंगतता की गारंटी नहीं देता है, केवल अनुक्रमिक स्थिरता।
अपडेट २
(5) अब इस उदाहरण की कल्पना करें (x = y = 0 और परमाणु हैं):
T1: x = 1;
T2: y = 1;
T3: if (x==1 && y==0) print("msg");
हमने जो बात की है, उसके अनुसार स्क्रीन पर प्रदर्शित "संदेश" हमें टी 1 के बाद निष्पादित की गई टी 2 से आगे की जानकारी नहीं देगा। तो या तो निम्नलिखित निष्पादन हो सकते हैं:
- टी 1 <टी 3 <टी 2
- T1 <T2 <T3 (जहां T3 x = 1 को देखता है लेकिन y = 1 को अभी तक नहीं)
क्या वह सही है?
(६) यदि कोई धागा हमेशा st बासी ’मूल्यों को पढ़ सकता है, तो क्या होगा यदि हमने ठेठ" प्रकाशित "परिदृश्य लिया, लेकिन संकेत देने के बजाय कि कुछ डेटा तैयार है, हम सिर्फ विपरीत (डेटा हटाएं) करते हैं?
T1: delete gameObjectPtr; is_enabled.store(false, std::memory_order_release);
T2: while (is_enabled.load(std::memory_order_acquire)) gameObjectPtr->doSomething();
जहां T2 अभी भी हटाए गए ptr का उपयोग कर रहा है, जब तक कि is_enabled गलत नहीं है।
(() इसके अलावा, यह तथ्य कि थ्रेड्स 'बासी' मूल्यों को पढ़ सकते हैं, का अर्थ है कि एक म्यूटेक्स को केवल एक लॉक-फ्री परमाणु अधिकार के साथ लागू नहीं किया जा सकता है? इसे थ्रेड्स के बीच एक सिंक्र तंत्र की आवश्यकता होगी। क्या इसके लिए लॉकबल परमाणु की आवश्यकता होगी?