2010-02-12 12 views
9

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

void foo::copy(const foo & rhs) 
{ 
    pMutex->lock(); 
    rhs.pMutex->lock(); 
    // do copy 
} 

फू में एक एसटीएल कंटेनर है और "प्रतिलिपि" अनिवार्य रूप से std :: copy का उपयोग करने के होते हैं। मैं डेडलॉक पेश किए बिना दोनों म्यूटेक्स को कैसे लॉक करूं?

उत्तर

15

foo के उदाहरणों पर किसी प्रकार का कुल आदेश लागू करें और हमेशा अपने ताले को या तो बढ़ते या घटते क्रम में प्राप्त करें, उदा।, foo1->lock() और फिर foo2->lock()

एक और दृष्टिकोण कार्यात्मक अर्थशास्त्र का उपयोग करना है और इसके बजाय foo::clone विधि लिखना है जो किसी मौजूदा व्यक्ति को क्लॉबर करने के बजाए एक नया उदाहरण बनाता है।

यदि आपका कोड लॉकिंग कर रहा है, तो आपको banker's algorithm जैसे जटिल डेडलॉक-टावरेंस एल्गोरिदम की आवश्यकता हो सकती है।

+0

भी आरएचएस बनाम इस के पते के रूप में सरल कुछ काम करेगा। हमेशा पहले निचले पते के साथ एक को लॉक करें। –

+0

क्लोन केवल तभी काम करेगा जब यह प्रतिलिपि नहीं बना रहा था, और मुझे नहीं लगता कि निहित साझाकरण काम करेगा, लेकिन मैं एक नज़र डालेगा। दिलचस्प दृष्टिकोण केली। मुझे कोई दोष नहीं दिख रहा है। – pomeroy

1

इस बारे में कैसे?

void foo::copy(const foo & rhs) 
{ 
    scopedLock lock(rhs.pMutex); // release mutex in destructor 
    foo tmp(rhs); 
    swap(tmp); // no throw swap locked internally 
} 

यह अपवाद सुरक्षित है, और सुंदर धागा भी सुरक्षित है। 100% थ्रेड सेव करने के लिए आपको सभी कोड पथ की समीक्षा करने और आंखों के दूसरे सेट के साथ दोबारा समीक्षा करने की आवश्यकता होगी, इसके बाद समीक्षा करें ...

-1

डेडलॉक से बचने के लिए यह संभवतः सबसे अच्छा है, दोनों संसाधनों बंद कर दिया जा सकता है:

न पता है जो म्युटेक्स आप ऐसा यहां का उपयोग कर रहे एपीआई कुछ मनमाने ढंग से छद्म कोड है, मान लेते हैं कि can_lock() केवल चेकों यह एक म्युटेक्स लॉक कर सकते हैं अगर, और कहा कि try_lock() रिटर्न सच अगर यह ताला था, और झूठे , अगर mutex पहले से किसी और द्वारा बंद कर दिया गया है।

void foo::copy(const foo & rhs) 
{ 
    for(;;) 
    { 
     if(! pMutex->cany_lock() || ! rhs.pMutex->cany_lock()) 
     { 
      // Depending on your environment call or dont call sleep() 
      continue; 
     } 
     if(! pMutex->try_lock()) 
      continue; 
     if(! rhs.pMutex->try_lock()) 
     { 
      pMutex->try_lock() 
      continue; 
     } 
     break; 
    } 
    // do copy 
} 
+2

डेडलॉक से बचने के लिए, एक livelock पेश करना सबसे अच्छा है? और स्पिन, 100% सीपीयू का उपयोग कर? – bk1e

-1

आप scoped_lock या auto_lock का उपयोग कर एक ही समय में दोनों mutexes ताला लगा की कोशिश कर सकते हैं .... बैंक हस्तांतरण करते हैं ...

void Transfer(Receiver recv, Sender send) 
{ 
    scoped_lock rlock(recv.mutex); 
    scoper_lock slock(send.mutex); 

    //do transaction. 
} 
संबंधित मुद्दे