2009-03-11 23 views
6

kod bir bölümünde kilit "bir defada bir" basit bir ihtiyaç.Basit Konu Senkronizasyon

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

Ben operation1 ve operation2 hep "birlikte" çalıştırmak emin olmak gerekir: birden çok iş parçacığı çalıştırılabilir işlev func düşünün. C# ile bu iki çağrı etrafında basit bir lock bloğu kullanırdım. C++/Win32/MFC eşdeğeri nedir?

Tahminen Mutex çeşit?

cevap

19

Kritik bölümler çalışacaktır (bunlar muteks ağırlıklardır.) InitializeCriticalSection, EnterCriticalSection, LeaveCriticalSection ve DeleteCriticalSection, MSDN'de aranacak işlevlerdir.

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

DÜZENLEME: kritik bölümleri öncelikle kullanıcı modu ilkel olduğundan Kritik bölümler muteksler daha hızlıdır - Bir uncontended edinilen (genellikle sık karşılaşılan durum) çekirdeğin içine hiçbir sistem çağrı var olması durumunda ve edinme alır düzinelerce döngü sırasına göre. Bir çekirdek anahtarı daha pahalı (yüzlerce döngüde). Kernelin çekirdeğe girmesini gerektiren tek zaman kritik bölümleri, bir çekirdek ilkelini (muteks veya olay) beklemeyi içeren, engellemek içindir. Bir muteks elde etmek, her zaman çekirdeğe bir çağrıyı içerir ve bu nedenle büyüklükleri daha yavaştır. Ancak kritik bölümleri tek işlemde kaynaklarını senkronize etmek kullanılabilir. Birden çok işlem arasında senkronize etmek için bir muteks gereklidir.

+0

Doğru şimdiye kadar, ama bildiğim kadarıyla CriticalSections içten muteksleri kullandığından, performans yararı yoktur. –

+0

Ve sonra istisna güvenliği için cs'yi bir sınıfa sarabilirsiniz; RAII'ye bakın. – Reunanen

+0

(Soru C++ ile ilgili olduğundan). – Reunanen

2

Bu deneyebilirsiniz:

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

WaitForSingleObject daha yavaştır. Kritik bölümler bir spin sayısı alabilir ve WaitForSingleObject'e düşmeden önce bir süre döneceklerdir. bkz http://msdn.microsoft.com/en-us/library/ms683476(VS.85).aspx InitializeCriticalSectionAndSpinCount Fonksiyon –

6

iyi yöntem EnterCriticalSection ve LeaveCriticalSection kullanın kritik bölümünü kullanmak olacaktır. Tek tıknaz kısım, ilk önce InitializeCriticalSection ile kritik bir bölümü başlatmanız gerektiğidir. Bu kod bir sınıf içinde ise, sınıfın bir üyesi olarak yapıcısında başlatma ve CRITICAL_SECTION veri yapısı koydu. Kod bir sınıfın parçası değilse, büyük olasılıkla bir kez başlatıldığından emin olmak için bir genel veya benzer bir şeyi kullanmanız gerekir.

6
  1. kullanılarak MFC:

    1. bir senkronizasyon nesnesi tanımlar. (Bağımlı veya Kritik bölüm)

      1.1 Farklı işlemlere ait birden fazla iş parçacığı func() 'a girerse, CMutex'i kullanın.

      1.2. Aynı işlemin birden çok parçacığı fonk girerse() daha sonra CCriticalSection kullanın.

    2. CSingleLock senkronizasyon nesnelerinin kullanım kolaylaştırmak için kullanılabilir.

kritik bölüm Tanımladığımız Diyelim

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(); 
    } 

DÜZENLEME: MSDN'den VC++ makalesine bakın: Multithreading with C++ and MFC Classes ve Multithreading: How to Use the Synchronization Classes

25

yukarıda Michael solution tamir ediyorum.

Michael çözümü C uygulamaları için mükemmeldir. Ancak C++ 'da kullanıldığında istisnaların ortaya çıkma olasılığı nedeniyle bu tarz önerilmemektedir. Operasyon1 veya operasyon2'de bir istisna meydana gelirse, kritik bölüm doğru şekilde bırakılmayacak ve diğer tüm mesajlar beklemeyi engelleyecektir.

// 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 iyi uygulama .. programlama – deepdive

+0

Sanat. Çok zarif. Kritik bölüm bloklarını ayırt etmek ve daha az hata yapmak daha kolay. :-) – StanE

+0

En İyi Yanıtlar hiç. :) – Mak