2013-07-18 2 views
5

간단한 질문 - 기본적으로 뮤텍스의 잠금을 해제해야합니까? 아니면 단순히 범위 연산자를 사용할 수 있습니까? 뮤텍스가 자동으로 잠금 해제됩니다.뮤텍스가 범위를 벗어날 때 잠금 해제됩니까?

예 :

{ 
    pthread_mutex_lock (&myMutex); 
    sharedResource++; 
} // my mutex is now unlocked? 

또는해야 내가 다음 RAII 범위의 방법을 사용하여

{ 
    pthread_mutex_lock (&myMutex); 
    sharedResource++; 
    pthread_mutex_unlock (&myMutex); 
} 
+5

어떤 뮤텍스 구현을 사용하고 있습니까? 뮤텍스 구현이 RAII를 지원하지 않는다면 명시 적으로 뮤텍스를 해제해야 할 것입니다. – Void

+0

고마워요 @ 보이드. 나는 pthread.h를 사용하고있다. 즉, pthread_mutex_unlock() 및 pthread_mutex_lock()입니다. RAII 란 무엇입니까? –

+3

@AmitNayar : http://en.wikipedia.org/wiki/Resource_Acquisition_Is_ 초기화를 참조하십시오.그것은 아마도 C++에서 가장 중요한 관용구 일 것입니다. 왜냐하면 메모리와 다른 동적 리소스를 제대로 관리하지 못하기 때문입니다. –

답변

16

뮤텍스가 예제에서 범위를 벗어나지 않습니다. 컴파일러가 특정 함수가 범위의 끝에서 호출해야한다는 것을 알 수있는 방법이 없으므로 첫 번째 예제는 이 아니며은 뮤텍스를 잠금 해제합니다.

(오류가 발생하기 쉬운) 함수를 사용하여 뮤텍스를 잠 그거나 잠금을 해제하는 경우 보호 된 연산이 예외를 throw하더라도 항상 unlock()을 호출해야합니다.

class lock_guard { 
public: 
    explicit lock_guard(mutex & m) : m(m) {mutex_lock(m);} 
    ~lock_guard() {mutex_unlock(m);} 

    lock_guard(lock_guard const &) = delete; 
    void operator=(lock_guard &) = delete; 

private: 
    mutex & m; 
}; 

// Usage 
{ 
    lock_guard lock(myMutex); 
    shared_resource++; 
} // mutex is unlocked here (even if an exception was thrown) 

++ 현대 C에 대한 std::lock_guard 또는 std::unique_lock를 사용하면 사용 후 방출 필요가 다른 자원 것처럼

이 작업을 수행하는 가장 좋은 방법은, 잠금을 관리 할 RAII 클래스를 사용하는 것입니다 이.

2

는 뮤텍스는 항상 초기 예외 또는의 얼굴에도 잠금을 해제 할 것을 보장하기 때문에 훨씬 더 반환.

C++ 11에 액세스 할 수있는 경우 std::atomic<int>을 사용하는 것이 좋지만이 경우에는 증가시키지 않고 잠글 수 있습니다.

2

이 경우 이 코드가 범위를 벗어날 때 뮤텍스는 잠금 해제되지 않습니다.

RAII 이후 뮤텍스 로커는 힙이 아닌 할당 된 객체가 범위를 벗어날 때 소멸자가 자동으로 호출된다는 사실을 사용합니다. 그런 다음 뮤텍스를 잠근 개체가 범위를 벗어나면 뮤텍스를 잠금 해제합니다. 코드의 경우 중괄호의 범위 내에서 객체가 할당되지 않으므로 범위가 끝나면 뮤텍스가 잠금 해제 될 가능성이 없습니다. Qt는 라이브러리에서 QMutexLocker를 사용하여 예를 들어

, 당신은 범위가 종료 할 때 뮤텍스 잠금이 해제되었는지 확인 할 수 있습니다

{ 
    QMutexLocker locker(myMutex); 
    if(checkSomething()) 
    { 
     return; 
    } 
    doSomething(); 
} 

이 코드는 비슷하다

{ 
    mutex_lock(myMutex); 
    if(checkSomething()) 
    { 
     mutex_unlock(myMutex); 
     return; 
    } 
    doSomething(); 
    mutex_unlock(myMutex); 
} 

브라이언로 비록 Neal은 예외가 발생하면 checkSomething()doSomething()이 예외를 throw하는 경우를 안전하게 처리하지 못한다고 지적합니다.

Qt의 QMutexLocker에 대한 대안은 STD의 std::lock_guard입니다.

+2

예외를 고려할 경우 두 코드 조각이 동일하지 않습니다. 그것들을 동일하게 만들려면'checkSomething'과'doSomething' 주위에 try/catch 블록을 추가해야합니다. RAII를 사용하는 첫 번째 예제를 선호하는 또 다른 이유. :) –

+0

좋은 지적, @ 브라이언 닐. 답변을 업데이트했습니다. 예외를 사용하지 말라는 점은 Qt 인프라가 필요하지 않으므로 다른 사람들이이를 고려해야한다는 것을 쉽게 잊는다. –

관련 문제