ProgramingTip

C ++ 11 : std :: condition_variable이 std :: unique_lock을 사용하는 이유는 무엇입니까?

bestdevel 2020. 11. 1. 18:26
반응형

C ++ 11 : std :: condition_variable이 std :: unique_lock을 사용하는 이유는 무엇입니까?


을 (를) std::unique_lock사용할 때 의 역할에 대해 약간 혼란 스럽 습니다 std::condition_variable. 내가 문서를 이해하는 한 , std::unique_lock기본적으로 두 개의 자물쇠 사이의 상태 를 바꿀 수있는 확장 된 자물쇠 가드입니다 .

나는 지금 pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)까지이 목적으로 사용되는 (STL이 posix에서 사용하는 것입니다). 잠금이 아닌 뮤텍스가 필요합니다.

여기서 차이점은 무엇입니까? 이것이 최적화 std::condition_variable다룬다 는 사실 std::unique_lock입니까? 정확히 얼마나 빠릅니까?


그 이유가 없나요?

나는 그가 작성한 이유를 제공했다고 믿기 때문에 cmeerw의 답변을 찬성했습니다. 보겠습니다. 하자가위원회로 결정했다 척 condition_variableA의 대기 mutex. 다음은 해당 디자인을 사용하는 코드입니다.

void foo()
{
    mut.lock();
    // mut locked by this thread here
    while (not_ready)
        cv.wait(mut);
    // mut locked by this thread here
    mut.unlock();
}

하나의 방법 이것은 정확히 을 사용합니다 condition_variable. 다음으로 새로운 지역에서 :

// mut locked by this thread here

예외 안전 문제가 심각한 문제입니다. 예외가 발생 하면 (또는 여기서) 예외가 발생 cv.wait하면 잠금을 해제하기 위해 예외를 어딘가에 배치되지 않는 한 뮤텍스의 잠긴 상태가 있습니다. 그러나 그것은 프로그래머에게 요구하는 코드에 불고기합니다.

프로그래머가 예외 안전 코드를 작성하는 방법을 알고 unique_lock있고 달성하기 위해 사용하는 방법을 알고 가정 해 보겠습니다 . 이제 코드는 다음과 달라집니다.

void foo()
{
    unique_lock<mutex> lk(mut);
    // mut locked by this thread here
    while (not_ready)
        cv.wait(*lk.mutex());
    // mut locked by this thread here
}

이것은 훨씬 낫지 만 여전히 좋은 상황은 아닙니다. condition_variable인터페이스는 프로그래머가 작업에 물건을 가지고 자신의 방식으로 외출하고 있습니다. lk실수로 뮤텍스를 참조하지 않는 경우 널 포인터 역 참조가 보관 수 있습니다 . 그리고이 condition_variable::wait행사가에 대한 잠금을 소유하고 있는지 확인 방법이 없습니다 mut.

오, 기억하십시오. 가 프로그래머 unique_lock뮤텍스를 노출하기 위해 잘못된 멤버 함수를 선택할 수있는 위험도 있습니다 . *lk.release()여기서는 재앙이 될 것입니다.

이제 다음을 사용하는 실제 condition_variableAPI로 코드를 작성하는 방법을 보겠습니다 unique_lock<mutex>.

void foo()
{
    unique_lock<mutex> lk(mut);
    // mut locked by this thread here
    while (not_ready)
        cv.wait(lk);
    // mut locked by this thread here
}
  1. 이 코드는 가능한 한 간단합니다.
  2. 예외적으로 안전합니다.
  3. wait함수 lk.owns_lock()는 예외가있는 경우 확인 하고 예외를 throw 할 수 있습니다 false.

.NET의 API 설계를 주도한 이유는 다음과 가변적 condition_variable입니다.

또한 당신이 말하는 방식 이기 때문에 condition_variable::wait를 사용하지 않습니다 . 그러나를 호출 하면 암시 적으로 뮤텍스에 대한 잠금을 해제합니다. 따라서 해당 작업은 사용 사례 / 문과 일치하지 않습니다 .lock_guard<mutex>lock_guard<mutex>lock_guard<mutex>condition_variable::waitlock_guard

unique_lock어쨌든 우리는 함수에서 잠금을 반환하고 컨테이너에 예외, 예외 방식으로 범위가 지정되지 않은 패턴으로 뮤텍스를 잠 그거나 잠금 해제 할 unique_lock수 있습니다 condition_variable::wait..

최신 정보

bamboon은 아래의 주석에서 내가 대조적으로 제안했습니다 condition_variable_any.

질문 :condition_variable::wait모든 Lockable유형을 전달할 수 있도록 템플릿 이 지정되지 않은 이유는 무엇 입니까?

대답 :

정말 멋진 기능입니다. 예를 들어, 이 문서shared_lock 는 조건 변수에 대해 공유 모드에서 (rwlock) 을 기다리는 코드를 보여줍니다 (posix 세계에서는 들어 보지 못했지만 그럼에도 불구하고 매우 유용함). 그러나 기능은 더 비쌉니다.

그래서위원회는이 기능을 가진 새로운 유형을 도입했습니다.

`condition_variable_any`

condition_variable 어댑터를 사용하면 모든 잠금 유형을 기다릴 수 있습니다 . 이 멤버가있는 경우 lock()unlock(), 당신은 갈 수 있습니다. 의 적절한 구현 condition_variable_any에는 condition_variable데이터 멤버와 데이터 멤버 필요합니다 shared_ptr<mutex>.

이 새로운 기능이 기본보다 더 많은 비용이 있기 때문에 condition_variable::wait, 그리고 있기 때문에이 condition_variable같은 낮은 수준의 도구이며,이 매우 유용하지만 더 비싼 기능이 있으므로 별도의 클래스에 넣고 그것을 위해 당신 만 지불 당신이 그것을 사용하는 경우 그.


기본적으로 API를 가능한 한 안전하게 만드는 것은 기본적으로 API 설계 결정입니다 (추가 오버 헤드는 무시할 수있는 것으로 간주 됨). API unique_lock의 원시 mutex사용자 대신 a를 전달하도록 요구함으로써 (예외가있는 경우) 올바른 코드를 작성하도록 안내합니다.

최근 몇 년 동안 C ++ 언어의 초점은 기본적으로 안전하게 만드는쪽으로 바뀌 었습니다 (그러나 사용자가 원할 경우 충분히 열심히 시도 할 수 있도록 허용).

참고 URL : https://stackoverflow.com/questions/13099660/c11-why-does-stdcondition-variable-use-stdunique-lock

반응형