std :: lock_guard 또는 std :: scoped_lock?


답변:


125

scoped_lock의 엄격 우수한 버전 lock_guard즉 (같은 교착 상태 회피 알고리즘 등을 이용하여 한번에 뮤텍스 모든 임의의 수를 잠근다 std::lock). 새 코드에서는을 사용해야합니다 scoped_lock.

lock_guard여전히 존재 하는 유일한 이유 는 호환성 때문입니다. 현재 코드에서 사용되기 때문에 삭제할 수 없습니다. 또한 정의를 변경하는 것은 바람직하지 않은 것으로 판명되었습니다. 단항에서 가변으로 변경하는 것도 관찰 가능하고 따라서 변경, 그러나 약간의 기술적 이유 때문에 변경되기 때문입니다.


8
또한 클래스 템플릿 인수 공제 덕분에 잠금 가능한 유형을 나열 할 필요조차 없습니다.
Nicol Bolas

3
@NicolBolas : 맞습니다.하지만에도 적용됩니다 lock_guard. 그러나 가드 클래스를 사용하기가 더 쉽습니다.
Kerrek SB

6
scoped_lock은 C ++ 17에만 해당
Shital Shah

1
c ++ 17이므로 호환성은 특히 존재하는 이유입니다. 또한이 표준에서 잉크가 계속 건조 될 때 "사용해야합니다"라는 절대주의 주장에 강력히 동의하지 않습니다.
Paul Childs

88

하나의 중요한 차이점은 std::scoped_lockvariadic 생성자가 둘 이상의 뮤텍스를 사용 한다는 것입니다. 이렇게하면 여러 뮤텍스를 교착 상태에서 잠그는 것처럼 피할 수 std::lock있습니다.

{
    // safely locked as if using std::lock
    std::scoped_lock<std::mutex, std::mutex> lock(mutex1, mutex2);     
}

이전에는 이 답변에std::lock 설명 된대로 여러 뮤텍스를 안전하게 고정하기 위해 약간의 춤을 추어 야했습니다 .

스코프 잠금 기능을 추가하면보다 쉽게 ​​사용할 수 있으며 관련 오류를 피할 수 있습니다. std::lock_guard더 이상 사용되지 않는 것으로 간주 할 수 있습니다 . 의 단일 인수 사례 std::scoped_lock는 전문화로 구현할 수 있으므로 가능한 성능 문제에 대해 걱정할 필요가 없습니다.

GCC 7은 이미 여기에서std::scoped_lock 볼 수있는 지원을 제공 합니다 .

자세한 내용은 표준 용지를 참조하십시오


9
10 분 후에 자신의 질문에 답변했습니다. 당신은 정말로 몰랐습니까?
Walter


3
위원회에서이 질문을 제기했을 때 대답은 "아무것도 아니 었습니다". 일부 알고리즘의 퇴화 사례 일 수 있습니다. 정확히 옳습니다. 또는 무언가를 잠그려고 할 때 충분한 사람들이 실수로 아무것도 잠그지 않는 것이 일반적인 문제 일 수 있습니다. 확실하지 않습니다.
하워드 힌 넌트

3
@HowardHinnant : scoped_lock lk; // locks all mutexes in scope. LGTM.
Kerrek SB

2
@KerrekSB : scoped_lock lk;의 새로운 속기입니다 scoped_lock<> lk;. 가 없습니다 더 뮤텍스는. 네 말이 맞아 ;-)
Howard Hinnant

26

답변이 늦었고 대부분 다음에 대한 응답으로 :

std::lock_guard더 이상 사용되지 않는 것으로 간주 할 수 있습니다 .

하나의 뮤텍스를 정확히 잠글 필요가있는 일반적인 경우 std::lock_guard보다 사용하기에 조금 더 안전한 API가 있습니다 scoped_lock.

예를 들면 다음과 같습니다.

{
   std::scoped_lock lock; // protect this block
   ...
}

위의 스 니펫은 컴파일 된 다음 전혀 아무것도하지 않기 때문에 우연히 런타임 오류 일 가능성이 큽니다. 코더는 아마도 다음을 의미했습니다.

{
   std::scoped_lock lock{mut}; // protect this block
   ...
}

이제 잠금 / 잠금 해제 mut됩니다.

lock_guard위의 두 예에서 대신 사용 된 경우 첫 번째 예는 런타임 오류 대신 컴파일 타임 오류이며 두 번째 예는를 사용하는 버전과 동일한 기능을 갖습니다 scoped_lock.

그래서 내 조언은 작업에 가장 간단한 도구를 사용하는 것입니다.

  1. lock_guard 전체 범위에 대해 정확히 1 개의 뮤텍스를 잠글 필요가있는 경우.

  2. scoped_lock 정확히 1이 아닌 여러 뮤텍스를 잠 가야하는 경우

  3. unique_lock 블록 범위 내에서 잠금을 해제해야하는 경우 ( condition_variable ).

이 조언 0 개의 뮤텍스를 허용하지 않도록 재 설계되어야 함을 의미 하지 않습니다scoped_lock . scoped_lock비어있을 수있는 가변 템플릿 매개 변수 팩을 수용하는 것이 바람직한 유효한 사용 사례 가 있습니다. 그리고 비어있는 경우는해야 하지 아무것도 잠급니다.

그리고 이것이 lock_guard더 이상 사용되지 않는 이유 입니다. scoped_lock unique_lock 의 기능의 상위 집합이 될 수 lock_guard있지만, 사실은 양날의 칼이다. 때로는 유형 수행하지 않는 것이 중요합니다 (이 경우 기본 구성).


13

다음은 C ++ 동시성 작업 의 샘플과 인용문입니다 .

friend void swap(X& lhs, X& rhs)
{
    if (&lhs == & rhs)
        return;
    std::lock(lhs.m, rhs.m);
    std::lock_guard<std::mutex> lock_a(lhs.m, std::adopt_lock);
    std::lock_guard<std::mutex> lock_b(rhs.m, std::adopt_lock);
    swap(lhs.some_detail, rhs.some_detail);
}

vs.

friend void swap(X& lhs, X& rhs)
{
    if (&lhs == &rhs)
        return;
    std::scoped_lock guard(lhs.m, rhs.m);
    swap(lhs.some_detail, rhs.some_detail);
}

존재 std::scoped_lock한다는 것은 std::lockc ++ 17 이전에 사용했던 대부분의 경우 std::scoped_lock를 실수로 사용할 가능성이 적은을 사용하여 작성할 수 있다는 것을 의미합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.