2012-10-25 3 views
6

मेरे पास एक क्लास इंस्टेंस है जिसका उपयोग अन्य थ्रेडों में संवाद करने के लिए कई अन्य वर्गों द्वारा किया जाता है।क्या एक सिंगल राइट/एकाधिक रीड लॉक का डेडलॉक हो सकता है?

static unsigned int readCounter = 0; 

class CReadLock 
{ 
public: 
    CReadLock(SRWLOCK& Lock) : m_Lock(Lock) { InterlockedIncrement(&readCounter); AcquireSRWLockShared(&m_Lock); } 
    ~CReadLock() {ReleaseSRWLockShared(m_Lock); InterlockedDecrement(&readCounter);} 

private: 
    SRWLOCK& m_Lock; 
}; 

class CWriteLock 
{ 
public: 
    CWriteLock(SRWLOCK& Lock) : m_Lock(Lock) { AcquireSRWLockExclusive(&m_Lock); } 
    ~CWriteLock() { ReleaseSRWLockExclusive(&m_Lock); } 

private: 
    SRWLOCK& m_Lock; 
}; 
समस्या

पूरी बात गतिरोध है:

इस वर्ग वास्तव में लॉक करने के लिए/बात अनलॉक एक तुल्यकालन वस्तु के रूप में एक स्लिम रीडर/राइटर ताला (WinAPI के SRWLOCK) और आरए II सहायक वर्गों की एक जोड़ी का उपयोग करता है पुरे समय। जब मैं डेडलॉक प्रोग्राम को रोकता हूं, तो मैं देखता हूं:

  • AcquireSRWLockExclusive() में एक थ्रेड फंस गया;
  • AcquireSRWLockShared() में फंस गए दो धागे;
  • readCounter वैश्विक 3.

के लिए रास्ता मैं इसे देखना सेट किया गया है, इस के लिए एक ही रास्ता होने की CReadLock उदाहरण नाशक किसी भी तरह कहीं तो ताला सदा अवरुद्ध हो गया है कहा जाता है नहीं किया गया है। हालांकि, ऐसा होने का एकमात्र तरीका (जहां तक ​​मुझे पता है) क्योंकि एक अपवाद फेंक दिया गया है। यह नहीं था। मैंने जाँचा।

समस्या क्या हो सकती है? मुझे इस बात को ठीक करने (या कम से कम इस कारण का पता लगाने) के बारे में कैसे जाना चाहिए?

उत्तर

9

क्या आप रिकर्सिव तरीके से रीड लॉक का उपयोग कर रहे हैं?

void foo() 
{ 
    CReadLock rl(m_lock); 
    ... 
    bar(); 
} 
void bar() 
{ 
    CReadLock rl(m_lock); 
    ... 
} 
void baz() 
{ 
    CWritedLock rl(m_lock); 
    ... 
} 

अगर foo() और baz() एक साथ कहा जाता है आप गतिरोध प्राप्त हो सकता है:

1. (Thread A) foo locks 
2. (Thread B) baz asks to create write lock now all read locks would block until all are released - waits. 
3. (Thread A) bar tries to lock and waits because there is pending write lock 

तथ्य यह है कि आप 2 धागे पढ़ें ताला और पढ़ें लॉक काउंटर पर अटक है 3 है कि सबसे अधिक संभावना से पता चलता है कि आप ताले में से एक में एक पुनरावर्तन - यानी एक थ्रेड ने दो बार पढ़ने के लिए लॉक हासिल करने की कोशिश की थी।

+0

'बार' को लॉक नहीं करना चाहिए? अगर 'foo' कॉलिंग' baz' (पता नहीं है कि ताले रिकर्सिव हैं) – Lol4t0

+0

आवश्यक नहीं है, तो Win32 API 'AcquireSRWLockShared' ** रिकर्सिव नहीं है ** POSIX के' pthread_rwlock_rdlock' या 'EnterCriticalSection' के विपरीत) – Artyom

+0

क्या आप साबित कर सकते हैं कि 'बाज लिखने के लिए अब पूछता है कि सभी पढ़े गए ताले तब तक अवरुद्ध हो जाएंगे जब तक सभी रिलीज़ नहीं हो जाते - इंतजार करते हैं।' चूंकि एमएसडीएन [कहता है] (http://msdn.microsoft.com/en-us/library/windows/desktop/aa904937%28v=vs.85%29.aspx): 'ऑर्डर के बारे में कोई गारंटी नहीं है जिसमें थ्रेड उस अनुरोध स्वामित्व को स्वामित्व दिया जाएगा; एसआरडब्ल्यू ताले न तो निष्पक्ष और न ही फीफो हैं। ' – Lol4t0

3
one thread stuck in AcquireSRWLockExclusive(); 
two threads stuck in AcquireSRWLockShared(); 
readCounter global is set to 3. 

ठीक है, जहाँ तक मैं इसे से पढ़ सकते हैं, तो आप एक धागा वर्तमान में पढ़ने लॉक रोक रखा है, एक लिखने धागा कि पढ़ ताला के लिए इंतजार जारी होने की, और दो के लिए कि धागा लिखने के लिए इंतज़ार कर धागे पढ़ लॉक प्राप्त करें और छोड़ दें।

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

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