2009-03-11 14 views
6

मुझे कोड के एक अनुभाग पर एक साधारण "एक समय में" लॉक की आवश्यकता है।सरल थ्रेड सिंक्रनाइज़ेशन

void func() 
{ 
    // locking/mutex statement goes here 
    operation1(); 
    operation2(); 
    // corresponding unlock goes here 
    operation3(); 
} 

मुझे यकीन है कि operation1 और operation2 हमेशा "एक साथ" चलाने बनाने की जरूरत है: समारोह func जो एक से अधिक थ्रेड से चलाया जा सकता पर विचार करें। सी # के साथ मैं इन दो कॉलों के आस-पास एक साधारण lock ब्लॉक का उपयोग करूंगा। सी ++/विन 32/एमएफसी समकक्ष क्या है?

संभवतः Mutex का कुछ प्रकार?

उत्तर

19

गंभीर वर्ग काम करेंगे (वे लाइटर-वेट हैं जो म्यूटेक्स हैं।) प्रारंभिक क्रिटिकलसेक्शन, एंटरक्रिटिकलसेक्शन, छोड़क्रिटिकलसेक्शन, और डिलीटक्रिटिकलसेक्शन एमएसडीएन पर देखने के लिए कार्य हैं।

void func() 
{ 
    // cs previously initialized via InitializeCriticalSection 
    EnterCriticalSection(&cs); 
    operation1(); 
    operation2(); 
    LeaveCriticalSection(&cs); 
    operation3();} 
} 

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

+0

अब तक सही है, लेकिन जहां तक ​​मुझे पता है कि क्रिटिकलसेक्शन आंतरिक रूप से म्यूटेक्स का उपयोग करते हैं, इसलिए प्रदर्शन लाभ नहीं होता है। –

+0

और फिर अपवाद सुरक्षा के लिए आप सीएस को कक्षा में लपेट सकते हैं; आरएआईआई देखें। – Reunanen

+0

(चूंकि प्रश्न सी ++ के बारे में है।) – Reunanen

2

आप इस कोशिश कर सकते हैं:

void func() 
{ 
    // See answer by Sasha on how to create the mutex 
    WaitForSingleObject (mutex, INFINITE); 
    operation1(); 
    operation2(); 
    ReleaseMutex(mutex); 
    operation3(); 
} 
+0

WaitForSingleObject धीमा है। क्रिटिकलक्शन एक स्पिन गिनती ले सकते हैं और WaitForSingleObject से गिरने से पहले थोड़ी देर के लिए स्पिन करेंगे। http://msdn.microsoft.com/en-us/library/ms683476(VS.85).aspx प्रारंभ करें क्रिटिकलसेक्शन एंडस्पिनकाउंट फ़ंक्शन –

6

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

6
  1. का उपयोग कर MFC:

    1. एक तुल्यकालन वस्तु को परिभाषित करें। (म्यूटटेक्स्ट या क्रिटिकल सेक्शन)

      1.1 यदि विभिन्न प्रक्रियाओं से संबंधित कई थ्रेड func() में प्रवेश करते हैं तो CMutex का उपयोग करें।

      1.2। यदि एक ही प्रक्रिया के कई थ्रेड func() में प्रवेश करते हैं तो CCriticalSection का उपयोग करें।

    2. सिंक्रनाइज़ेशन ऑब्जेक्ट्स के उपयोग को कम करने के लिए CSingleLock का उपयोग किया जा सकता है।

चलें कहते हैं कि हम परिभाषित किया है महत्वपूर्ण अनुभाग

CCriticalSection m_CriticalSection; 
    void func() 
    { 
     // locking/mutex statement goes here 
     CSingleLock aLock(&m_CriticalSection, **TRUE**); 
     // TRUE indicates that Lock aquired during aLock creation. 
     // if FALSE used then use aLock.Lock() for locking. 

     operation1(); 
     operation2(); 
      // corresponding unlock goes here 
      aLock.Unlock(); 
     operation3(); 
    } 

संपादित करें: MSDN से देखें कुलपति ++ लेख: ऊपर Multithreading with C++ and MFC Classes और Multithreading: How to Use the Synchronization Classes

25

फिक्सिंग Michael solution

माइकल समाधान सी अनुप्रयोगों के लिए बिल्कुल सही है। लेकिन जब सी ++ में उपयोग किया जाता है तो अपवादों की स्थिरता के कारण यह शैली निराश होती है। यदि ऑपरेशन 1 या ऑपरेशन 2 में कोई अपवाद होता है तो महत्वपूर्ण अनुभाग सही ढंग से नहीं छोड़ा जाएगा और अन्य सभी थ्रेड प्रतीक्षा को अवरुद्ध कर देंगे।

// Perfect solutiuon for C applications 
void func() 
{ 
    // cs previously initialized via InitializeCriticalSection 
    EnterCriticalSection(&cs); 
    operation1(); 
    operation2(); 
    LeaveCriticalSection(&cs); 
    operation3();} 
} 

// A better solution for C++ 
class Locker 
{ 
    public: 
    Locker(CSType& cs): m_cs(cs) 
    { 
     EnterCriticalSection(&m_cs); 
    } 
    ~Locker() 
    { 
     LeaveCriticalSection(&m_cs); 
    } 
    private: 
     CSType& m_cs; 
} 
void func() 
{ 
    // cs previously initialized via InitializeCriticalSection 
    { 
     Locker lock(cs); 
     operation1(); 
     operation2(); 
    } 
    operation3(); 
} 
+0

+1 RAII सर्वोत्तम अभ्यास .. – deepdive

+0

प्रोग्रामिंग की कला। बहुत खूबसूरत। महत्वपूर्ण अनुभाग ब्लॉक और गलतियों को कम करने की संभावना कम करने के लिए आसान है। :-) – StanE

+0

सर्वोत्तम उत्तर कभी भी। :) – Mak

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