2015-06-17 6 views
7

मैं pthread (C++ 98 मानक) का उपयोग कर एक बहुप्रचारित C++ प्रोग्राम बना रहा हूं।सी ++ मानचित्र के लिए थ्रेड सिंक्रनाइज़ेशन

मेरे पास एक std :: नक्शा है जो एकाधिक धागे तक पहुंच जाएगा। पहुंच [] ऑपरेटर का उपयोग करके तत्वों को जोड़ने और निकालने के लिए तत्वों को जोड़कर और हटाएगी।

मैं समझता हूं कि [] ऑपरेटर का उपयोग करके पढ़ना, या इसके साथ तत्वों को संशोधित करना भी धागा सुरक्षित है, लेकिन शेष परिचालन नहीं हैं।

पहला प्रश्न: क्या मैं इसे सही ढंग से समझता हूं?

कुछ धागे केवल [] के माध्यम से तत्वों तक पहुंचेंगे, जबकि अन्य कुछ अन्य परिचालन करेंगे। जाहिर है मुझे थ्रेड सिंक्रनाइज़ेशन के कुछ रूप की आवश्यकता है।

जिस तरह से मुझे यह देखना चाहिए, यह है: - हालांकि मानचित्र पर कोई "लिखना" ऑपरेशन नहीं किया जा रहा है, धागे सभी को इसके साथ "पढ़ने" में सक्षम होना चाहिए। - जब कोई धागा मानचित्र पर "लिखना" चाहता है, तो उसे लॉक सेट करना चाहिए ताकि कोई थ्रेड किसी भी "पठन" या "लिखने" ऑपरेशन को शुरू न करे, और फिर इसे तब तक इंतजार करना चाहिए जब तक कि सभी "पढ़े" ऑपरेशन पूर्ण नहीं हो जाते हैं, किस बिंदु पर यह ऑपरेशन करेगा और ताले को छोड़ देगा। - ताले जारी किए जाने के बाद, सभी धागे स्वतंत्र रूप से पढ़ने में सक्षम होना चाहिए।

मुख्य प्रश्न यह है कि: इस व्यवहार को प्राप्त करने के लिए मैं किस थ्रेड सिंक्रनाइज़ेशन विधियों का उपयोग कर सकता हूं?

मैंने म्यूटेक्स, सशर्त चर और सेमफोरों के बारे में पढ़ा है, और जहां तक ​​मैं देख सकता हूं कि वे मुझे जो चाहिए वह उत्कृष्टता से नहीं करेंगे। मैं mutex से परिचित हूँ लेकिन cond के साथ नहीं। चर या semaphores।

मुझे लगता है कि मुख्य समस्या यह है कि जब तक कुछ घटित नहीं होता है (लिखना ऑपरेशन समाप्त होता है) तब तक धागे को लॉक करने का एक तरीका चाहिए, फिर बदले में कुछ भी लॉक कर दें। इसके अलावा मुझे एक उल्टा सेमफोर की तरह कुछ चाहिए, जो कि काउंटर 1 से अधिक होने पर ब्लॉक करता है और फिर 0 होता है जब जागता है (यानी कोई पढ़ा नहीं जा रहा है)।

अग्रिम धन्यवाद।

पीएस यह मेरी पहली पोस्ट है। कृपया संकेत दें कि क्या मैं कुछ गलत कर रहा हूं!

+1

क्या आपको केवल एक पाठक-लेखक म्यूटेक्स चाहिए? –

+1

आपको आरडब्लू लॉक की आवश्यकता है, [इस उदाहरण।] (Http://stackoverflow.com/questions/989795/example-for-boost-shared-mutex-multiple-reads-one-write) – gbjbaanb

+0

एक अच्छी पहली पोस्ट। निश्चित रूप से आप [सी ++ 11] (http://en.cppreference.com/w/cpp/thread) का उपयोग नहीं कर सकते हैं? यह आपके कोड को सरल बना देगा, और इसे और अधिक पोर्टेबल बना देगा। कंटेनर तत्वों की प्रकृति के आधार पर, आपको भारी थ्रेड सुविधाओं की आवश्यकता नहीं हो सकती है। शायद [सिंक] (http://en.cppreference.com/w/cpp/atomic) primitives पर्याप्त होगा। –

उत्तर

6

मैं समझता हूँ कि [] ऑपरेटर का उपयोग पढ़ने, या यहाँ तक कि इसके साथ तत्वों को संशोधित धागा सुरक्षित है, लेकिन आपरेशन के बाकी नहीं हैं।

क्या मैं इसे सही ढंग से समझता हूं?

ठीक है, आपने जो कहा है वह बिल्कुल सही नहीं है। समवर्ती पाठकों [] का उपयोग मौजूदा तत्वों का उपयोग कर सकते हैं, या अन्य const कार्यों का उपयोग (जैसे find, size() ...) सुरक्षित रूप से अगर कोई एक साथ गैर const संचालन की तरह erase या insertmap<> परिवर्तनशील है। समवर्ती धागे विभिन्न तत्वों को संशोधित कर सकते हैं, लेकिन यदि एक थ्रेड किसी तत्व को संशोधित करता है तो आपके पास किसी अन्य थ्रेड को उस विशिष्ट तत्व को एक्सेस करने या आगे संशोधित करने से पहले कुछ सिंक्रनाइज़ेशन होना चाहिए।

एक धागा नक्शा करने के लिए "लिखने" के लिए करना चाहता है, तो वह एक ताला तो कोई धागा किसी भी "पढ़ें" या "लिखने" आपरेशन शुरू होता है स्थापित करना चाहिए, और फिर यह सब "पढ़ें" संचालन पूर्ण नहीं करने तक इंतजार करना चाहिए , जिस बिंदु पर यह ऑपरेशन करेगा और ताले को छोड़ देगा। - ताले जारी किए जाने के बाद, सभी धागे स्वतंत्र रूप से पढ़ने में सक्षम होना चाहिए।

यही काफी नहीं जिस तरह से यह काम करता है ... लेखकों करने में सक्षम होने के लिए है 'इंतजार सब जब तक "पढ़ें" आपरेशन पूरा कर लिया है', पाठक (रों) एक ताला प्राप्त करने के लिए की जरूरत है। लेखक तब उसी लॉक को रिलीज़ होने की प्रतीक्षा करते हैं, और अन्य पाठकों या लेखकों को प्रतिबंधित करने के लिए खुद को प्राप्त करते हैं जब तक कि वे अपना अपडेट पूरा नहीं कर लेते हैं और इसे छोड़ देते हैं।

इस व्यवहार को प्राप्त करने के लिए मैं किस थ्रेड सिंक्रनाइज़ेशन विधियों का उपयोग कर सकता हूं?

एक म्युटेक्स, वास्तव में उपयुक्त है, हालांकि आप अक्सर एक पाठक लेखक ताला से उच्च प्रदर्शन मिल जाएगा (जो समवर्ती पाठकों की अनुमति देता है, कुछ भी आगे पाठकों से अधिक लेखकों इंतजार कर prioritorise)। संबंधित POSIX धागे कार्यों में शामिल हैं:

THREAD ACTION 
reader1 pthread_mutex_lock(the_mutex) returns having acquired lock, and 
     thread starts reading data 
reader2 pthread_mutex_lock(the_mutex) "hangs", as blocked by reader1 
writer1 pthread_mutex_lock(the_mutex) hangs, as blocked by reader1 
reader1 pthread_mutex_unlock(the_mutex) -> releases lock 
NOTE: some systems guarantee reader2 will unblock before writer1, some don't 
reader2 blocked pthread_mutex_lock(the_mutex) returns having acquired lock, 
     and thread starts reading data 
reader1 pthread_mutex_lock(the_mutex) hangs, as blocked by reader2 
reader2 pthread_mutex_unlock(the_mutex) -> releases lock  
writer1 blocked pthread_mutex_lock(the_mutex) returns having acquired lock, 
     and thread starts writing and/or reading data 
writer1 pthread_mutex_unlock(the_mutex) -> releases lock  
reader1 blocked pthread_mutex_lock(the_mutex) returns having acquired lock, 
     and thread starts reading data 
...etc... 

एक पढ़ने-लिखने की है: pthread_rwlock_rdlock, pthread_rwlock_wrlock, pthread_rwlock_unlock आदि ..

एक म्युटेक्स का उपयोग कर आप इस तरह क्रमबद्धता कुछ पाने पाठकों और लेखकों के साथ दो दृष्टिकोण विपरीत करने के लिए, लॉक करें, यह इस तरह अधिक हो सकता है (पहले दो पाठकों को एक साथ चलते हैं):

THREAD ACTION 
reader1 pthread_rwlock_rdlock(the_rwlock) returns having acquired lock, and 
     thread starts reading data 
reader2 pthread_rwlock_rdlock(the_rwlock) returns having acquired lock, and 
     thread starts reading data 
writer1 pthread_rwlock_wrlock(the_rwlock) hangs, as blocked by reader1/2 
reader1 pthread_rwlock_unlock(the_rwlock) -> releases lock 
reader1 pthread_rwlock_rwlock(the_rwlock) hangs, as pending writer 
reader2 pthread_rwlock_unlock(the_rwlock) -> releases lock  
writer1 blocked pthread_rwlock_wrlock(the_rwlock) returns having acquired lock, 
     and thread starts writing and/or reading data 
writer1 pthread_rwlock_unlock(the_rwlock) -> releases lock  
reader1 blocked pthread_rwlock_rwlock(the_rwlock) returns having acquired lock, 
     and thread starts reading data 
...etc... 
+0

पढ़ने/लिखने वाले ताले वास्तव में मुझे चाहिए। उनके बारे में नहीं पता था! धन्यवाद। – Dan

+1

स्थिति के आधार पर, मल्टीवर्सन कंसुरेंसी एक विकल्प हो सकता है, जैसे किसी ऑब्जेक्ट की बजाय मानचित्र में 'shared_ptr' डालकर किया जा सकता है। पाठक साझा सूचक की प्रतिलिपि बनाते हैं और एक लेखक परमाणु रूप से इसे दूसरे स्थान से बदल देता है। इस प्रकार, जब तक उनकी आवश्यकता नहीं होती है तब तक वस्तुओं को मानचित्र में उनके अस्तित्व को आगे बढ़ाया जाता है। ध्यान दें कि साझा पॉइंटर्स के चारों ओर प्रतिलिपि बनाना बिल्कुल "मुक्त" नहीं है, यह आपके द्वारा किए गए कार्यों के आधार पर पाठक-लेखक लॉक से तेज़ या धीमा हो सकता है। – Damon

+0

@ डैमन: अच्छा सुझाव - शायद एक अलग उत्तर के रूप में है, या सीधे सवाल के तहत टिप्पणी ...? निश्चित रूप से आप तक। चीयर्स। –

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