2009-03-11 4 views
6

코드 섹션에서 간단한 "한 번에 1 회"잠금이 필요합니다.간단한 스레드 동기화

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

내가 operation1operation2 항상 "함께"를 실행하는지 확인해야합니다 여러 스레드에서 실행할 수있는 기능 func을 고려하십시오. C#에서는이 두 호출을 중심으로 간단한 lock 블록을 사용합니다. C++/Win32/MFC는 무엇입니까?

아마도 Mutex 일종의?

답변

19

중요 섹션이 작동합니다 (뮤텍스보다 가볍습니다). InitializeCriticalSection, EnterCriticalSection, LeaveCriticalSection 및 DeleteCriticalSection은 MSDN에서 찾을 함수입니다.

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

편집 : 중요한 섹션은 주로 사용자 모드 원시 있기 때문에 중요한 섹션 뮤텍스보다 더 빠르다 - 경쟁이 없었던 취득 (보통 일반적인 경우) 커널에 어떤 시스템 호출이없는 경우에, 그리고 획득 소요 수십 사이클 정도. 커널 스위치는 더 비쌉니다 (수 백 사이클 정도). 중요한 섹션이 커널에 호출되는 유일한 시간은 커널 프리미티브 (뮤텍스 또는 이벤트)를 기다리는 것을 포함하여 차단하기위한 것입니다. 뮤텍스를 얻는 것은 항상 커널에 대한 호출을 필요로하므로 더 느리게 진행됩니다. 그러나 중요한 섹션은 한 프로세스에서 리소스를 동기화하는 데만 사용할 수 있습니다. 여러 프로세스간에 동기화하려면 뮤텍스가 필요합니다.

+0

지금까지 수정했지만 CriticalSections는 내부적으로 뮤텍스를 사용하므로 성능상의 이점이 없습니다. –

+0

그리고 예외 안전을 위해 클래스에 cs를 래핑 할 수 있습니다. RAII 참조. – Reunanen

+0

(질문은 C++에 관한 것입니다.) – Reunanen

2

이 작업을 시도 할 수 있습니다 :

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

WaitForSingleObject가 더 느립니다. CriticalSections는 회전 수를 취할 수 있으며 잠시 동안 회전하여 WaitForSingleObject로 떨어집니다. http://msdn.microsoft.com/en-us/library/ms683476(VS.85).aspx InitializeCriticalSectionAndSpinCount 함수를 참조하십시오. –

6

가장 좋은 방법은 EnterCriticalSection과 LeaveCriticalSection를 사용, 크리티컬 섹션을 사용하는 것입니다. 중요한 부분은 InitializeCriticalSection을 사용하여 중요한 섹션을 먼저 초기화해야한다는 것입니다. 이 코드가 클래스 내에 있으면 생성자에 초기화를 넣고 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에서 VC++ 문서를 참조하십시오 Multithreading with C++ and MFC ClassesMultithreading: How to Use the Synchronization Classes

25

Michael solution 고정.

마이클 솔루션은 C 애플리케이션에 이상적입니다. 그러나 C++에서 사용되는 경우 예외의 가능성 때문에이 스타일은 권장되지 않습니다. operation1 또는 operation2에서 예외가 발생하면 critical 섹션은 올바르게 남지 않으며 다른 모든 스레드는 대기를 차단합니다.

// 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