2010-11-17 16 views
7

मेरे पास एक एसएलएल वेक्टर और एक एसएलएल सूची को संशोधित करने वाले कई धागे हैं।
यदि कंटेनर खाली है तो मैं लॉक लेने से बचना चाहता हूंक्या एसटीएल खाली है() थ्रेडसेफ?

क्या निम्न कोड थ्रेडसेफ होगा? क्या होगा अगर आइटम एक सूची या नक्शा था?

class A 
{ 
    vector<int> items 
    void DoStuff() 
    { 
     if(!items.empty()) 
     { 
      AquireLock(); 
      DoStuffWithItems(); 
      ReleaseLock(); 
     } 
    } 
} 
+0

प्रतिक्रियाओं के लिए धन्यवाद। प्रश्न को स्पष्ट करने के लिए: अन्य धागे आइटम में जोड़ देंगे। आइटम से कोई अन्य धागा नहीं हटाएगा - हटाएगा केवल DoStuffWithItems() के अंदर होगा और केवल एक ही थ्रेड DoStuff() को कॉल करेगा। यह ठीक है अगर item.empty() झूठी रिटर्न देता है जबकि एक और धागा इसमें जोड़ रहा है। यह ठीक नहीं है अगर आइटम्स.empty() एप्लिकेशन को क्रैश करने का कारण बनता है यदि कोई अन्य थ्रेड इसमें जोड़ रहा है –

उत्तर

6

यह निर्भर करता है कि आप क्या उम्मीद करते हैं। अन्य उत्तरों सही हैं सामान्य में, मानक सी ++ कंटेनर थ्रेड-सुरक्षित नहीं हैं, और इसके अलावा, विशेष रूप से में आपका कोड पर आपके कॉल के बीच कंटेनर को संशोधित करने वाले किसी अन्य थ्रेड के खिलाफ वार्ड नहीं करता है और इसके अधिग्रहण लॉक (लेकिन यह मामला vector::empty की धागा सुरक्षा से असंबंधित है)।

तो, किसी भी गलतफहमी को दूर करने के लिए: आपका कोड items ब्लॉक के अंदर खाली नहीं होगा।

लेकिन आपका कोड अभी भी उपयोगी हो सकता है, क्योंकि आप जो करना चाहते हैं वह अनावश्यक लॉक रचनाओं से बचने के लिए है। आपका कोड गारंटी नहीं देता है लेकिन एक अनावश्यक लॉक निर्माण को रोक सकता है। यह सभी मामलों में काम नहीं करेगा (अन्य थ्रेड अभी भी आपके चेक और लॉक के बीच कंटेनर खाली कर सकते हैं) लेकिन में मामले हैं। और यदि आप सब कुछ एक अनावश्यक ताला छोड़कर एक अनुकूलन है, तो आपका कोड उस लक्ष्य को पूरा करता है।

बस सुनिश्चित करें कि किसी भी वास्तविक पहुँच कंटेनर करने के लिए ताले द्वारा संरक्षित है या नहीं।

वैसे, ऊपर सख्ती से बोल रहा है अपरिभाषित व्यवहार: एक एसटीएल कार्यान्वयन सैद्धांतिक रूप से empty करने के लिए कॉल के अंदर mutable सदस्यों को संशोधित करने के लिए अनुमति दी है। इसका मतलब यह होगा कि स्पष्ट रूप से हानिरहित (केवल पढ़ने के लिए) emptyपर कॉल वास्तव में एक संघर्ष का कारण बन सकता है। दुर्भाग्यवश, आप इस धारणा पर भरोसा नहीं कर सकते कि केवल-पढ़ने वाली कॉल एसटीएल कंटेनरों के साथ सुरक्षित हैं।

व्यवहार में, हालांकि, मैं बहुत यकीन है कि vector::emptyकिसी भी सदस्य नहीं संशोधित करेंगे।लेकिन पहले से ही list::empty के लिए मुझे कम यकीन है। यदि आप वास्तव में की गारंटी देते हैं, तो या तो प्रत्येक एक्सेस को लॉक करें या STL कंटेनर का उपयोग न करें।

1

एसटीएल थ्रेड सुरक्षित और खाली भी नहीं है। यदि आप कंटेनर को सुरक्षित बनाना चाहते हैं तो आपको म्यूटेक्स या अन्य सिंक

3

द्वारा अपने सभी तरीकों को बंद करना होगा एसटीएल के कंटेनर और एल्गोरिदम में कुछ भी थ्रेड-सुरक्षित गारंटी नहीं है।

तो, सं

2

या नहीं, खाली की परवाह किए बिना धागा सुरक्षित है, अपने कोड नहीं लिखा के रूप में, अपना लक्ष्य प्राप्त होगा।

class A 
{ 
    vector<int> items 
    void DoStuff() 
    { 
     if(!items.empty()) 
     { 
      //Another thread deletes items here. 
      AquireLock(); 
      DoStuffWithItems(); 
      ReleaseLock(); 
     } 
    } 
} 

एक बेहतर समाधान (, जब पुनरावृत्ति आइटम हो रही, आइटम जोड़ने, जाँच गिनती/खालीपन, आदि), इस प्रकार अपने स्वयं के धागे सुरक्षा उपलब्ध कराने के हर बार जब आप items के साथ काम लॉक करने के लिए है। तो, पहले लॉक प्राप्त करें, फिर जांचें कि वेक्टर खाली है या नहीं।

+0

आपका पॉइंट (// एक और थ्रेड यहां आइटम हटा देता है।) स्पष्ट है। फिर भी यह भी स्पष्ट है कि आप सुनिश्चित करने के लिए लॉक प्राप्त करने के बाद खाली() को चेक कर सकते हैं। –

+0

@skwllsp: एक मान्य बिंदु। यदि 'खाली()' थ्रेड सुरक्षित है, पहले रिक्त स्थान की जांच कर रहा है, लॉक कर रहा है, और फिर पुन: जांच एक अनावश्यक ताला से बच सकता है। – Brian

0

जैसा कि पहले से ही उत्तर दिया गया है, उपरोक्त कोड थ्रेड सुरक्षित नहीं है और वास्तव में कंटेनर के साथ कुछ भी करने से पहले लॉकिंग अनिवार्य है। लेकिन निम्नलिखित लॉकिंग से बेहतर प्रदर्शन होना चाहिए और मैं इस कारण से नहीं सोच सकता कि यह असुरक्षित हो सकता है। यहां विचार यह है कि लॉकिंग महंगा हो सकती है और जब भी वास्तव में आवश्यकता नहीं होती है, हम इससे बच रहे हैं।

class A 
{ 
    vector<int> items; 
    void DoStuff() 
    { 
     if(!items.empty()) 
     { 
      AquireLock(); 
      if(!items.empty()) 
      { 
       DoStuffWithItems(); 
      } 
      ReleaseLock(); 
     } 
    } 
} 
संबंधित मुद्दे