태그 보관물: multithreading

multithreading

std :: lock_guard 또는 std :: scoped_lock? 도입했습니다 std::scoped_lock. 문서에서 판단하면 기존 std::lock_guard클래스 와

C ++ 17은이라는 새로운 잠금 클래스를 도입했습니다 std::scoped_lock.

문서에서 판단하면 기존 std::lock_guard클래스 와 비슷하게 보입니다 .

차이점은 무엇이며 언제 사용해야합니까?



답변

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

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


답변

하나의 중요한 차이점은 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 볼 수있는 지원을 제공 합니다 .

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


답변

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

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있지만, 사실은 양날의 칼이다. 때로는 유형 수행하지 않는 것이 중요합니다 (이 경우 기본 구성).


답변

다음은 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를 실수로 사용할 가능성이 적은을 사용하여 작성할 수 있다는 것을 의미합니다.


답변