2010-09-03 15 views
5

क्या थ्रेड-सुरक्षित होने के लिए यहां अस्थायी उपयोग करना आवश्यक है?परमाणु लौटा है और क्या मुझे गेट में सुरक्षित होने के लिए अस्थायी उपयोग करना चाहिए?

int getVal() { 
     this->_mutex.lock(); 
     int result = this->_val; 
     this->_mutex.unlock(); 
     return result; 
} 

मैं तुम्हें सरल आरए II परीक्षण समारोह के disassembly दे देंगे

int test() 
{ 
    RAIITest raii; //let's say it's a scoped lock 
    return 3; 
} 


{ 
    0x004013ce <_Z4testv>: push %ebp 
    0x004013cf <_Z4testv+1>: mov %esp,%ebp 
    0x004013d1 <_Z4testv+3>: sub $0x28,%esp 
    return 3; 
    0x004013d4 <_Z4testv+6>: lea -0x18(%ebp),%eax 
    0x004013d7 <_Z4testv+9>: mov %eax,(%esp) 
    0x004013da <_Z4testv+12>: call 0x4167a0 <_ZN8RAIITestD1Ev> //here destructor is called 
    0x004013df <_Z4testv+17>: mov $0x3,%eax //here result is pushed onto the stack 
} 
0x004013e4 <_Z4testv+22>: leave 
0x004013e5 <_Z4testv+23>: ret 

संकलक है जीसीसी/जी ++ 3.4.5

+0

::: आकस्मिक रूप से इसे सी # और वीटीसी के रूप में पढ़ें। माफ़ कीजिये। – Brian

+0

मुझे नहीं लगता कि आपका आरएआईआई उदाहरण क्या साबित करना है। निरंतर लौटने पर बस कंपाइलर को चिल्लाता है कि धोखा देना और अनुकूलित करना ठीक है क्योंकि वापसी मूल्य प्रभावित नहीं होगा। – jalf

उत्तर

5

this->_val के लिए उपयोग this->_mutex द्वारा सिंक्रनाइज़ है, तो आप डॉन वर्तमान में कोड लिखा गया तरीका पसंद नहीं है। म्यूटएक्स को अनलॉक करने से पहले आपको this->_val पढ़ने की आवश्यकता है और आपको वापस आने से पहले म्यूटेक्स को अनलॉक करना होगा। क्रियाओं के इस आदेश को प्राप्त करने के लिए result चर आवश्यक है।

आप उपयोग करते हैं एक lock_guard (या scoped_lock बूस्ट में), तो आप अस्थायी उपयोग करने के लिए क्योंकि म्युटेक्स पर ताला जब समारोह रिटर्न जारी किया जाएगा जरूरत नहीं है। उदाहरण के लिए, का उपयोग करते हुए C++ 0x धागे पुस्तकालय:

int getVal() { 
    std::lock_guard<std::mutex> lock(_mutex); 
    return this->_val; 
} // lock is released by lock_guard destructor 
+0

नहीं, यह नहीं होगा। यदि यह -> _ वैल एक अंतर्निहित परिणाम बिल्कुल वही होगा। और ऑब्जेक्ट (scoped_lock) को स्टैक पर धक्का देने से पहले नष्ट कर दिया जाता है। – doc

+2

@ डॉक: क्या नहीं होगा? ऑब्जेक्ट की प्रतिलिपि वापस आने के बाद तक स्थानीय चर 'लॉक' नष्ट नहीं किया जाएगा। –

+0

मैंने अपने प्रश्न – doc

1

हाँ अगर आप स्पष्ट लॉक का उपयोग()/अनलॉक()। नहीं, यदि आप स्टैक पर लॉक ऑब्जेक्ट बनाते हैं और इसके विनाशक अनलॉक करते हैं।

+0

क्यों? वापसी के कारण परिणाम धकेलने से पहले ऑब्जेक्ट को नष्ट कर दिया जाता है। – doc

+0

ऐसा नहीं है।इस कोड पर विचार करें: std :: string f() { std :: string ret = "abc"; रिटर्न रिट; } यदि रिटर्न स्टेटमेंट से पहले 'रेट' नष्ट हो गया था, तो इसे फ़ंक्शन के रिटर्न वैल्यू के रूप में कॉपी किया गया था, f() उदाहरण के लिए कचरा वापस कर सकता है, अगर बिलकुल भी। – usta

+0

@usta आंतरिक प्रकार चुनना आसान है। निर्माण, विनाश, ये उच्च स्तरीय शब्द हैं। दृश्यों के पीछे आमतौर पर एक निश्चित एबीआई द्वारा परिभाषित फ़ंक्शन कॉल स्टैक पर धक्का दिया जाता है। और मुझे परेशान करता है, क्या परिणाम होने से पहले म्यूटेक्स के विनाशक को बुलाया जाता है। – doc

0

नहीं - संकलक स्वचालित रूप से वापसी मूल्य के लिए अस्थायी बनाता है। आपको आमतौर पर म्यूटेक्स के साथ पढ़ने की आवश्यकता नहीं होती है, भले ही इसके बहुप्रचारित, return _val; पर्याप्त होना चाहिए।

एक तरफ, मैं अग्रणी अंडरस्कोर से छुटकारा पाउंगा - नियमों के बारे में नियम जो आप अंडरस्कोर से शुरू करते समय उपयोग कर सकते हैं और उपयोग नहीं कर सकते हैं, पर्याप्त जटिल हैं कि केवल उनसे बचने के लिए बेहतर है।

+0

जेरी आपकी टिप्पणी को पढ़ने के लिए लॉक की आवश्यकता नहीं है, क्योंकि यह एक int है, क्या यह सही है? अधिक जटिल प्रकारों के लिए आप एक ही समय में समेकित लिखना नहीं चाहेंगे क्योंकि कॉपी निर्माण के बारे में मैंने सोचा होगा। धन्यवाद। –

+0

@ स्टेव: हां। बेशक, मानक में कुछ भी नहीं कहता है कि यह उस तरह से होना चाहिए (चूंकि मानक बिल्कुल थ्रेडिंग को कवर नहीं करता है), लेकिन एक व्यावहारिक दृष्टिकोण से, एक int अनिवार्य रूप से हमेशा परमाणु है। –

+0

लेकिन म्यूटेक्स अनलॉक होने के बाद उस अस्थायी की "प्रतिलिपि" होती है। यदि तब एक धागा निलंबित कर दिया जाएगा और दूसरा धागा '_val' को संशोधित करेगा (मैंने इस उदाहरण में अंडरस्कोर लगाया है कि यह एक वर्ग सदस्य है (लेकिन फिर मैंने इसे 'यह->' भी बेहतर तरीके से इंगित करने के लिए जोड़ा है) तो मुझे क्षमा करें) "प्रतिलिपि" के दौरान, परिणाम संभवतः रूबी बन सकता है। मुझे पता है कि अभ्यास में ऐसा नहीं होना चाहिए, लेकिन मैं जानना चाहता हूं कि ट्रूली थ्रेड-सुरक्षित क्या है। – doc

0

आप ऐसा कर सकते हैं सफाई से अपने म्युटेक्स एक scoped_lock कि विनाश पर बातें बताता में समझाया जाता है:

int getVal() { 
     scoped_lock lockit(_mutex); 
     return _val; 
} 

और हाँ, आप जब तक यह लौटाई गई ताला पकड़ की जरूरत है।

+0

_val निर्मित प्रकार के मामले में, डिस्सेप्लर बिल्कुल गैर-स्कोप्ड लॉक के मामले में समान दिखाई देगा – doc