2013-08-08 9 views
7

मेरे पास एक चर int foo है जो दो धागे से उपयोग किया जाता है। मान लीजिए कि मेरे पास कोई रेस-कंडीशन समस्या नहीं है (एक्सेस म्यूटेक्स द्वारा संरक्षित है, सभी परिचालन परमाणु हैं, या दौड़ की स्थिति से बचाने के लिए जो भी अन्य तरीका है), अभी भी "रजिस्टर कैशिंग" का मुद्दा है (बेहतर नाम की कमी के लिए) , जहां संकलक मान सकते हैं कि यदि चर के बीच में लिखा जा रहा बिना दो बार पढ़ रहा है, यह एक ही मूल्य है, और इसलिए की तरह दूर बातें "अनुकूलन" हो सकता है:थ्रेड के बीच परिवर्तनीय सिंक करने के लिए 'अस्थिर'

while(foo) { // <-may be optimized to if(foo) while(1) 
    do-something-that-doesn't-involve-foo; 
} 

या

if(foo) // becomes something like (my assembly is very rusty): mov ebx, [foo]; cmp ebx, 0; jz label; 
    do-something-that-doesn't-involve-foo; 
do-something-else-that-doesn't-involve-foo; 
if(foo) // <-may be optimized to jz label2; 
    do-something; 

foo को volatile के रूप में चिह्नित करते हुए इस समस्या को हल करते हैं? क्या एक थ्रेड से परिवर्तन अन्य धागे तक पहुंचने की गारंटी है?

यदि नहीं, तो ऐसा करने का दूसरा तरीका क्या है? मुझे लिनक्स/विंडोज (संभवतः अलग समाधान) के लिए समाधान की आवश्यकता है, कोई सी ++ 11 नहीं।

+0

मैं मानक से एक उद्धरण देख रहा हूं कि आप सी ++ में थ्रेड के लिए अस्थिरता का उपयोग नहीं करना चाहते हैं, मैं इसे – aaronman

+3

http: // stackoverflow ढूंढने की कोशिश करूंगा।कॉम/प्रश्न/4557979/जब-से-उपयोग-अस्थिर-साथ-बहु-थ्रेडिंग –

+1

यहां समस्या यह है कि "मुझे लगता है कि मेरे पास कोई रेस-हालत समस्या नहीं है"। यह एक ** मनोरंजक ** धारणा है। –

उत्तर

11

आपको स्मृति बाधाओं की आवश्यकता है।

MemoryBarrier(); 

या

__sync_synchronize(); 

संपादित करें: मैं दिलचस्प हिस्सा बोल्ड कर दिया है और यहाँ विकी लेख (http://en.wikipedia.org/wiki/Memory_barrier#cite_note-1) और संबद्ध संदर्भ (http://www.rdrop.com/users/paulmck/scalability/paper/whymb.2010.07.23a.pdf)

यहाँ के लिए लिंक है का जवाब आपका अन्य प्रश्न (विकिपीडिया से): सी और सी ++ में, अस्थिर कीवर्ड का उद्देश्य सी और सी ++ प्रोग्रामों को स्मृति-मैप किए गए I/O तक सीधे पहुंचने की अनुमति देना था। मेमोरी-मैप किए गए I/O को आम तौर पर आवश्यकता होती है कि स्रोत कोड में निर्दिष्ट पढ़ और लिखने के लिए कोई भी चूक के साथ निर्दिष्ट सटीक क्रम में होता है। कंपाइलर द्वारा पढ़ने और लिखने के ओमिशन या रीडरिंग प्रोग्राम और स्मृति-मैप किए गए I/O द्वारा एक्सेस किए गए डिवाइस के बीच संचार को तोड़ देंगे। एक सी या सी ++ कंपाइलर पुन: व्यवस्थित नहीं हो सकता है और अस्थिर स्मृति स्थानों को लिखता है, न ही यह एक अस्थिर स्मृति स्थान को पढ़ या लिख ​​सकता है। कीवर्ड अस्थिर कैश-स्थिरता को लागू करने के लिए स्मृति बाधा की गारंटी नहीं देता है। http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2 http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2: इसलिए अकेले की "अस्थिर" उपयोग सभी प्रणालियों और प्रोसेसर [1]

चेक इस एक बाहर है, यह इस विषय पर महान जानकारी प्रदान पर अंतर-धागा संचार के लिए एक चर का उपयोग करने के लिए पर्याप्त नहीं है

9

यदि पहुंच mutex द्वारा संरक्षित है, तो आपको चिंता करने की कोई समस्या नहीं है। volatile कीवर्ड यहां बेकार है। एक म्यूटेक्स एक पूर्ण मेमोरी बाधा है और इस प्रकार कोई ऑब्जेक्ट जिसका पता बाहरी रूप से दिखाई नहीं दे सकता है उसे म्यूटेक्स लॉक में कैश किया जा सकता है या कॉल अनलॉक किया जा सकता है।

+0

सच है। म्यूटेक्स कैश-स्थिरता का ख्याल रखता है। – MasterPlanMan

+0

स्पष्टता के लिए: कैश द्वारा मेरा मतलब केवल मशीन-स्तरीय कैश नहीं था, बल्कि रजिस्टरों में मानकों के कैशर का कैश भी था। –

1

volatile कीवर्ड मूल रूप से यह इंगित करने के लिए पेश किया गया था कि मूल्य हार्डवेयर द्वारा बदला जा सकता है। ऐसा तब होता है जब हार्डवेयर डिवाइस में मेमोरी मैप किए गए रजिस्ट्रार या मेमोरी बफर होते हैं। सही उद्देश्य केवल इस उद्देश्य के लिए इसका उपयोग करना है।

सभी आधुनिक सिंक्रनाइज़ेशन भाषा संरचनाएं और सिंक्रनाइज़ेशन लाइब्रेरी इस कीवर्ड का उपयोग नहीं कर रहे हैं। आवेदन स्तर प्रोग्रामर एक ही काम करना चाहिए।

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