2011-10-26 11 views
18

निम्नलिखित कोड पर:std :: परमाणु <int> घटती और तुलना

std::atomic<int> myint; //Shared variable 
//(...) 
if(--myint == 0) { 
    //Code block B 
} 

क्या यह संभव है कि एक से अधिक धागा पहुँच ब्लॉक मैं "कोड ब्लॉक B" का नाम?

कृपया विचार है कि अतिप्रवाह नहीं होगा, कि 'अगर' एक से अधिक थ्रेड के समवर्ती निष्पादित किया जा रहा है, कि पूरे कार्यक्रम में मींट के लिए एक ही संशोधन --myint अंदर है अगर और कि माइंट एक सकारात्मक मूल्य के साथ शुरू किया गया है।

+0

आपको क्यों लगता है कि यह संभव नहीं होना चाहिए? यदि यह एकमात्र ऑपरेशन है जिसे आप 'मायिंट' पर करते हैं तो अंततः यह बह जाएगा। – Patrick

+1

@ पैट्रिक जो अपरिभाषित व्यवहार होगा। –

+2

असली सवाल यह है कि अगर std :: atomic :: ऑपरेटर - परमाणु रूप से पुराना मान देता है। – cdleonard

उत्तर

16

C++ 0x कागज N2427 (एटोमिक्स) मोटे तौर पर निम्नलिखित में कहा गया है। मैं शब्दों को बदल दिया है थोड़ा इसलिए इसकी आसान विशिष्ट घटती स्थिति के लिए पढ़ने के लिए, भागों मैं बदल बोल्ड में हैं:

प्रभाव: atomically मूल्यवस्तु में का परिणाम के साथ बदलें कमीमूल्यऑब्जेक्ट और दिए गए ऑपरेंड में लागू किया गया। आदेश के अनुसार स्मृति प्रभावित है। ये ऑपरेशंस [2323 या उत्तराधिकारी द्वारा जोड़े गए नए खंड] में परिभाषा के साथ "सिंक्रनाइज़" परिभाषा के अर्थ में पढ़-संशोधित-लेखन कार्य हैं, और इसलिए इनपुट मूल्य उत्पन्न करने वाले मूल्यांकन और मूल्यांकन दोनों मूल्यांकन के साथ सिंक्रनाइज़ करते हैं अद्यतन मूल्य पढ़ता है।

रिटर्न: atomically, तुरंत घटती से पहले वस्तु का मूल्य।

परमाणु ऑपरेशन गारंटी देता है कि कमीशन ऑपरेटर ऑपरेशन से ठीक पहले आयोजित वैरिएबल को वापस लौटाएगा, यह परमाणु है इसलिए किसी अन्य धागे द्वारा अपडेट से कोई मध्यवर्ती मूल्य नहीं हो सकता है।

इसका मतलब यह है 2 धागे के साथ हैं इस कोड का केवल संभव फांसी के बाद:

(Initial Value: 1) 
Thread 1: Decrement 
Thread 1: Compare, value is 0, enter region of interest 
Thread 2: Decrement 
Thread 2: Compare, value is -1, don't enter region 

या

(Initial Value: 1) 
Thread 1: Decrement 
Thread 2: Decrement 
Thread 1: Compare, value is 0, enter region of interest 
Thread 2: Compare, value is -1, don't enter region 

केस 1 अरुचिकर उम्मीद मामला है।

केस 2 कमी संचालन को रोकता है और बाद में तुलना संचालन निष्पादित करता है। चूंकि कमी-और-fetch ऑपरेशन परमाणु है, इसलिए धागा 1 के लिए तुलना के लिए 0 के अलावा अन्य मान प्राप्त करना असंभव है। यह नहीं प्राप्त कर सकता है क्योंकि ऑपरेशन परमाणु था ... पढ़ने के समय पढ़ने और पर पढ़ने के समय होता है। अधिक धागे इस व्यवहार को नहीं बदलेंगे।

+3

ध्यान दें कि मैंने N3291 की जांच की है, और हालांकि यह अलग-अलग शब्दों का उपयोग करता है, यह इसके साथ सहमत है। –

+0

क्या यह अभी भी "--myint;" (myint == 0) {} "के लिए सही है? – paulm

+2

@paulm यदि आप दो अलग-अलग बयानों में कमी और जांच करते हैं तो यह बिल्कुल सही नहीं है। एक ही बयान में किया जाना है। – SoapBox

-1

नहीं, यह संभव नहीं है कि एक से अधिक धागे ब्लॉक में प्रवेश करें, आपकी बाधाओं को देखते हुए।

thread A: decrement myint to 0 

thread B: decrement myint to -1 

thread A: compare to 0 -> false -> don't enter (and neither anyone else) 

यह एक समस्या (जो मुझे लगता है) है, तो इस कोड काम नहीं करेगा (कम से कम हमेशा नहीं): लेकिन न तो यह गारंटी है कि किसी भी धागा कभी भी इस ब्लॉक में प्रवेश करती है।

+1

तो अगर मेरे पास है: थ्रेड ए: 1 से कमी, थ्रेड बी: 0 में कमी, थ्रेड ए : 0 सत्य की तुलना करें, थ्रेड बी: 0 सत्य की तुलना करें। –

+0

@ AndréPuel आह, मुझे लगता है कि तुमने मुझे (और आपका जवाब) मिला है। –

+0

@ AndréPuel यह संभव नहीं है, - ऑपरेटर एक निर्देश में कमी करता है और प्राप्त करता है, इसलिए आपके टिप्पणी में निर्दिष्ट निष्पादन आदेश में भी थ्रेड ए में मान 1 होगा। – SoapBox

1

यह स्पष्ट नहीं है कि कोड ब्लॉक हमेशा निष्पादित होगा। यदि ऑपरेटर "-" को इस तरह कार्यान्वित किया जाता है कि यह पुराने मूल्य को अपने लौटने वाले मूल्य और एक परमाणु निर्देश में कमी (मुझे यकीन है कि x86 में ऐसे निर्देश हैं), तो हां, इसे एक जैसा कार्य करना चाहिए एकाधिक धागे के लिए पारस्परिक बहिष्करण ब्लॉक। मुझे यकीन है कि कैसे यह डिफ़ॉल्ट रूप से काम करता है नहीं कर रहा हूँ, लेकिन इस सवाल का जवाब शायद नए मानक दस्तावेज में निहित है:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2427.html

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