2012-03-23 17 views
5

मेरे साझा डेटा संरचना की सुरक्षा के लिए लॉक का उपयोग करने के बारे में मेरे कुछ प्रश्न हैं। मैं उपयोग कर रहा हूँ C/C++/ObjC/ObjC++मल्टीथ्रेडिंग: क्या मुझे अपने चर को केवल-पढ़ने की विधि में सुरक्षित रखने की आवश्यकता है?

उदाहरण के लिए मैं एक काउंटर वर्ग है जो बहु-धागा वातावरण में प्रयुक्त है

class MyCounter { 
private: 
    int counter; 
    std::mutex m; 

public: 
    int getCount() const { 
     return counter; 
    } 
    void increase() { 
     std::lock_guard<std::mutex> lk(m); 
     counter++; 
    } 
}; 
  1. मैं getCount() विधि में std::lock_guard<std::mutex> lk(m); उपयोग करने के लिए इसे बनाने के लिए की जरूरत है सुरक्षित धागा?

  2. क्या होता है यदि केवल दो धागे हैं: एक पाठक धागा और एक लेखक धागा तो क्या मुझे इसे सुरक्षित रखना होगा? क्योंकि केवल एक धागा चर को संशोधित कर रहा है, इसलिए मुझे लगता है कि कोई खोया अपडेट नहीं होगा।

  3. कई एक साझा आदिम प्रकार चर के लिए लेखक/पाठक नहीं हैं, तो (जैसे int) क्या आपदा अगर मैं केवल लिखने विधि में बंद है, लेकिन विधि पढ़ा नहीं हो सकता है? 8 बिट्स प्रकार 64 बिट्स प्रकार की तुलना में कोई अंतर करेगा?

  4. क्या कोई आदिम प्रकार डिफ़ॉल्ट रूप से परमाणु है? उदाहरण के लिए char पर लिखें हमेशा परमाणु है? (मैं जानता हूँ कि यह जावा में सच है लेकिन सी के बारे में ++ पता नहीं है और मैं मैक पर LLVM संकलक का उपयोग कर रहा है, तो मंच मामलों)

+1

"C/C++/ObjC/ObjC++" ये सब पूरी तरह से अलग अलग भाषाओं (एमएस C++ के लिए उपलब्ध)। एक चुनें; ऐसा लगता है कि आपने सी ++ चुना है। – GManNickG

+0

मैं बैकएंड और ओबीजेसी ++ के लिए जीयूआई और सी ++ के लिए ओबीजेसी का उपयोग कर रहा हूं ताकि उन्हें गठबंधन किया जा सके। ओबीजेसी ++ दूसरों के सुपरसेट भी है। उदाहरण के तौर पर मैं बस सी ++ चुनता हूं। –

+0

यह अच्छा है, लेकिन उन्हें एक सूची में एक साथ संयोजित न करें। :) बस कहें कि आप चार अलग-अलग भाषाओं में एक उत्तर में रूचि रखते हैं। – GManNickG

उत्तर

7

हाँ, जब तक कि आप गारंटी ले सकते हैं अंतर्निहित चर counter में परिवर्तन परमाणु हैं कि, आपको म्यूटेक्स चाहिए।

क्लासिक उदाहरण के लिए, कहते हैं कि counter एक दो बाइट मूल्य कि (गैर परमाणु) के चरणों में वृद्धि की जाती है:

add 1 to lower byte 
if lower byte is 0: 
    add 1 to upper byte 

और प्रारंभिक मूल्य 255

एक और धागा के बीच कहीं भी में आता है, तो है निचला बाइट परिवर्तन और ऊपरी बाइट परिवर्तन, यह सही 255 (पूर्व-वृद्धि) या 256 (बाद में वृद्धि) के बजाय 0 पढ़ेगा।

डेटा प्रकार परमाणु के संदर्भ में, नवीनतम सी ++ मानक उन्हें <atomic> शीर्षलेख में परिभाषित करता है।

यदि आप पर सी ++ 11 क्षमताओं नहीं हैं, तो यह कार्यान्वयन के लिए नीचे है कि किस प्रकार परमाणु हैं।

+0

मैं सोच रहा था कि हम 32/64 बिट सीपीयू का उपयोग कर रहे हैं, जिसे एक समय में 32 बिट आकार परिवर्तक को दो चरणों में विभाजित किया जाना चाहिए? –

+0

@ xlc0212, ऑपरेटिव शब्द "चाहिए" है। हर तरह से, यदि आप इसे सत्यापित कर सकते हैं, तो आप ठीक हो सकते हैं। लेकिन यह सिर्फ एक सीपीयू पर धागे का एक साधारण मामला नहीं है, आप कई सीपीयू, इंटरप्ट्स और कवर के तहत होने वाली अन्य आश्चर्यजनक चीजों का उपयोग कर सकते हैं। – paxdiablo

+0

@ xlc0212 जो काम नहीं करेगा (विश्वसनीय/अनुमानित रूप से); आपके पास अनुक्रमिक स्थिरता है, सख्त स्थिरता नहीं है। अगर आप सिक्योरेंशियल को सख्त के रूप में देखते हैं तो आप क्या देखते हैं "करीबी, लेकिन काफी नहीं", और कार्यक्रम में केवल खराब कीड़े होंगी। – justin

3

हां, आपको इस मामले में पढ़ने को भी लॉक करना होगा।

कई विकल्प हैं - यहां एक लॉक काफी भारी है। परमाणु संचालन सबसे स्पष्ट (ताला मुक्त) हैं। इस डिज़ाइन में लॉक करने के अन्य दृष्टिकोण भी हैं - रीड राइट लॉक एक उदाहरण है।

+1

+1, लेकिन एक नोट के रूप में: सी ++ में 'std :: atomic' प्रकार लॉक मुक्त होने की गारंटी नहीं है। वे अधिकतर प्लेटफार्मों पर पूर्णांक के लिए लॉक फ्री होंगे, लेकिन यह एक स्पष्ट गारंटी नहीं है (हालांकि आप इसके लिए जांच सकते हैं)। – KillianDS

+0

@ किलियनडीएस धन्यवाद - अच्छा बिंदु। – justin

1

हाँ, मेरा मानना ​​है कि आपको पढ़ने को भी लॉक करने की आवश्यकता है। लेकिन चूंकि आप सी ++ 11 फीचर्स का उपयोग कर रहे हैं, तो आप इसके बजाय std::atomic<int> counter; का उपयोग क्यों नहीं करते?

+0

एक और समस्या है: '#error लागू नहीं किया गया है '। ऐसा हुआ अगर मैं ' –

0

आप यह गारंटी नहीं दे सकते कि एकाधिक थ्रेड एक ही समय में आपके चर को संशोधित नहीं करेंगे। और यदि ऐसी स्थिति होती है तो आपका चर खराब हो जाएगा या प्रोग्राम क्रैश हो सकता है। ऐसे मामलों से बचने के लिए प्रोग्राम थ्रेड को सुरक्षित बनाने के लिए यह हमेशा बेहतर और सुरक्षित होता है।

आप तुल्यकालन techinques उपयोग कर सकते हैं उपलब्ध की तरह: Mutex, लॉक, तुल्यकालन विशेषता

+0

शामिल करने का प्रयास करता हूं तो उसने वास्तव में गारंटी दी थी कि एक ही समय में एकाधिक धागे नहीं लिख सकते हैं। रीड-लॉक को छोड़ना अभी भी सही नहीं है लेकिन अन्य कारणों से (अन्य उत्तरों में पोस्ट किया गया है)। – KillianDS

+0

सिंक्रनाइज़ेशन का उपयोग किये बिना एक बहु थ्रेडेड स्थिति में वह कितना सुनिश्चित हो सकता है? –

+0

'वृद्धि' (केवल गैर-कॉन्स विधि) सिंक्रनाइज़ेशन का उपयोग करती है, और साझा डेटा' निजी' – MSalters

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