2010-08-10 21 views
5

मुझे एक ऐसा फ़ंक्शन बनाने की आवश्यकता है जो एक वेक्टर के लिए मूल्य जोड़ती है और उस मूल्य के सूचकांक को वापस लौटाती है जो अभी संलग्न थी।परमाणु रूप से std :: vector :: push_back() और वापसी सूचकांक

उदाहरण:

int append(std::vector<int>& numbers, int number){ 
    int retval = numbers.size(); 
    // what if some other thread calls push_back(number) in between these calls? 
    numbers.push_back(number); 
    return retval; 
} 

ताकि लौटे सूचकांक हमेशा सही जब भी वहाँ एक से अधिक थ्रेड वेक्टर के लिए मान जोड़कर हो सकता है मैं इस atomically करना चाहते हैं। push_back ने आइटम की अनुक्रमणिका को वापस जोड़ा तो यह आसान होता। मैं कैसे गारंटी दे सकता हूं कि सही सूचकांक वापस आ गया है?

+5

दरअसल, पुश_बैक() ने इंडेक्स लौटाया तो यह आसान नहीं होगा, क्योंकि push_back() स्वयं थ्रेड सुरक्षित नहीं है –

+0

आपको अपने कंटेनर को सभी समवर्ती लेखनों के विरुद्ध सुरक्षित रखने की आवश्यकता है। समवर्ती सादे push_back() को पहले से ही वेक्टर-बाहरी सिंक्रनाइज़ेशन की आवश्यकता है –

+3

ध्यान रखें कि कई वास्तविक-दुनिया अनुप्रयोगों के लिए, छोटे थ्रेड-सुरक्षित संचालन करना सही समाधान नहीं है: आपको कोड के बड़े हिस्से की सुरक्षा करने पर विचार करना चाहिए।यदि आप उन्हें संचार तंत्र के रूप में उपयोग कर रहे हैं तो थ्रेड-सुरक्षित संग्रह अच्छे हैं। उस ने कहा, यह एक ऐसा मामला हो सकता है। –

उत्तर

11

std::vector थ्रेड समर्थन में कोई निर्मित नहीं है। आप इसे विस्तार करने के लिए इस्तेमाल कर सकते हैं boost::mutex:

int append(std::vector<int>& numbers, int number){ 
    boost::mutex::scoped_lock slock(my_lock); 
    int retval = numbers.size(); 
    numbers.push_back(number); 
    return retval; 
} 

आप इस तरह के रास्ते में किसी भी पढ़ें/लिखें आपरेशन की रक्षा के लिए की जरूरत है। एक और तरीका है std::vector के लिए रैपर वर्ग बनाना जो इसे थ्रेड समर्थन के साथ बढ़ाएगा। विवरण के लिए this प्रश्न देखें।

+1

यह कैसे काम करता है जब कोई अन्य थ्रेड इस फ़ंक्शन को कॉल करने के अलावा वेक्टर के साथ कुछ करता है? एक अन्य थ्रेड कॉलिंग नंबर। स्क्लर() यहां scoped_lock का सम्मान नहीं करेगा। –

+0

यह काम करेगा, लेकिन यह केवल इस एकल ऑपरेशन को सुरक्षित करेगा। कोई भी एक ही वस्तु पर 'push_back()' कहीं और कर सकता है और इसे तोड़ सकता है। – sharptooth

+4

किसी को पढ़ने/लिखने के संचालन की रक्षा करने की आवश्यकता है। हो सकता है कि ओपी को 'std :: vector' के लिए रैपर क्लास बनाना चाहिए जो इसे थ्रेड समर्थन के साथ बढ़ाएगा। विवरण के लिए [यह] जांचें (http://stackoverflow.com/questions/1099513/threadsafe-vector-class-for-c) प्रश्न। –

3

एसटीएल कंटेनर थ्रेड-सुरक्षित नहीं हैं (यहां तक ​​कि push_back() पर भी कॉल करें), आपको इस समस्या को स्वयं हल करना होगा - एसटीएल के बाहर कुछ उपयुक्त सिंक्रनाइज़ेशन प्राइमेटिव का उपयोग करें।

0

आप गारंटी नहीं है कि सही सूचकांक दिया जाता है एक म्युटेक्स उपयोग करने की आवश्यकता

+0

यह वास्तव में एक टिप्पणी है, सवाल का जवाब नहीं। लेखक के लिए प्रतिक्रिया छोड़ने के लिए कृपया "टिप्पणी जोड़ें" का उपयोग करें। –

+2

असहमत। मेरा मानना ​​है कि यह एक जवाब है। स्वीकृत उत्तर भी एक ही सलाह देता है लेकिन एक उदाहरण के साथ। –

0

सबसे मजबूत-गारंटी समाधान ऐसे सभी कार्यों पर पूरी सदिश (जो कोड में हर जगह से नियंत्रित करने का मतलब है हर आपरेशन लॉक करने के लिए है , जो वास्तव में एक सिंक्रनाइज़ वेक्टर बनाने का मतलब है)।

हो सकता है कि इस के रूप में सरल कुछ अपने उद्देश्यों के लिए करना होगा:

इस बारे में
int append(std::vector<int>& numbers, int number){ 
    int retval = numbers.size(); 
    // what if some other thread calls push_back(number) in between these calls? 
    numbers.push_back(number); 
    int newSize = numbers.size(); 
    //this bit is as a short-cut in common, easy, cases 
    if(newSize = retval + 1) //no need for further complication 
    return retval; 
    while(++retval < newSize) 
    if(numbers[retval] == number) 
     return retval; 
    //If we get this far, numbers have been deleted, not added. More discussion below. 
} 

एक बात यह है कि अगर धागे धक्का 3, 3, 3, 3 तो सूचकांक लौटे गलत हो जाएगा, हालांकि यह अभी भी एक सूचकांक होगा 3. चाहे वह ठीक है या नहीं, आपके उद्देश्यों पर निर्भर करता है।

दूसरा यह है कि अगर वेक्टर पॉप या अन्यथा कम हो जाता है, तो सबसे अच्छा यह है कि हम उस बिंदु पर पहुंच जाते हैं जहां मैंने ऊपर दिए गए कोड में एक टिप्पणी डाली है, इससे भी बदतर त्रुटियां हैं (जैसे ही हम प्राप्त करने के बाद फिर से पॉप करते हैं नया आकार, और फिर [retval] तक पहुंच अमान्य हो जाता है)। आपको यह विचार करने की आवश्यकता है कि क्या यह मामला हो सकता है (शायद आप उस कोड के बाकी हिस्सों से जानते हैं जो कभी नहीं करेगा) और यदि ऐसा होता है तो क्या करना है।

यदि आपके उपयोग के मामले में इसकी सीमाएं बहुत अच्छी हैं, तो पूरी तरह सिंक्रनाइज़ वेक्टर का उत्पादन करना सबसे अच्छा है, मुझे लगता है कि मैं डरता हूं।

2

विजुअल स्टूडियो 2010 में, आप इसके लिए concurrent_vector का उपयोग कर सकते हैं, यह सिंक्रनाइज़ बढ़ने की कार्यक्षमता प्रदान करता है। This topic प्रत्येक समवर्ती कंटेनर सूचीबद्ध करता है।

ध्यान दें कि ये इंटेल के टीबीबी में समान वाक्यविन्यास + अर्थशास्त्र के साथ भी उपलब्ध हैं और जैसे क्रॉस प्लेटफॉर्म उपलब्ध हैं।

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