program tip

재귀 뮤텍스를 언제 사용합니까?

radiobox 2021. 1. 8. 08:05
반응형

재귀 뮤텍스를 언제 사용합니까?


재귀 뮤텍스를 사용하면 교착 상태에 도달하지 않고 뮤텍스를 두 번 이상 잠글 수 있으며 같은 횟수만큼 잠금을 해제해야한다는 것을 이해합니다. 그러나 어떤 특정 상황에서 재귀 뮤텍스를 사용해야합니까? 디자인 / 코드 수준의 상황을 찾고 있습니다.


예를 들어 재귀 적으로 호출하는 함수가 있고 이에 대한 동기화 된 액세스를 얻으려는 경우 :

void foo() {
   ... mutex_acquire();
   ... foo();
   ... mutex_release();
}

재귀 뮤텍스가 없으면 먼저 "진입 점"함수를 만들어야하는데, 상호 재귀적인 함수 집합이있을 때 이것은 번거로워집니다. 재귀 뮤텍스없이 :

void foo_entry() {
   mutex_acquire(); foo(); mutex_release(); }

void foo() { ... foo(); ... }

재귀 및 비 재귀 뮤텍스는 사용 사례다릅니다 . 뮤텍스 유형은 다른 유형을 쉽게 대체 할 수 없습니다. 비 재귀 뮤텍스는 오버 헤드가 적고, 재귀 뮤텍스는 어떤 상황에서는 유용하거나 심지어 필요한 의미론을 가지고 있으며 다른 상황에서는 위험하거나 심지어는 의미론을 깨뜨립니다. 대부분의 경우 누군가는 재귀 뮤텍스를 사용하는 모든 전략을 비 재귀 뮤텍스 사용에 따라 더 안전하고 효율적인 다른 전략으로 대체 할 수 있습니다.

  • 다른 스레드가 뮤텍스 보호 리소스를 사용하지 못하도록 제외하려면 모든 뮤텍스 유형을 사용할 수 있지만 오버 헤드가 더 작기 때문에 비 재귀 뮤텍스를 사용할 수 있습니다.
  • 동일한 뮤텍스를 잠그는 함수를 재귀 적으로 호출하려면
    • 사용해야 하나의 재귀 뮤텍스를 , 또는
    • 동일한 비재 귀적 뮤텍스를 반복해서 잠금 해제하고 잠 가야합니다 (동시 스레드에주의하십시오!) (이것이 의미 상 건전하다고 가정하면 여전히 성능 문제 일 수 있음).
    • 이미 잠근 뮤텍스에 주석을 달아야합니다 (재귀 적 소유권 / 뮤텍스 시뮬레이션).
  • 병합을 통해 집합을 만들 수있는 이러한 개체 집합에서 여러 뮤텍스 보호 개체를 잠 그려면 다음을 선택할 수 있습니다.
    • 객체 당 정확히 하나의 뮤텍스 를 사용 하여 더 많은 스레드가 병렬로 작동하도록 허용합니다.
    • 모든 뮤텍스를 함께 잠그는 데 실패 할 가능성을 낮추기 위해 가능한 공유 재귀 뮤텍스에 대한 하나의 참조객체별로 사용 하거나
    • 여러 번 잠 그려는 의도를 우회하여 가능한 공유 비 재귀 뮤텍스에 대한 하나의 비교 가능한 참조객체별로 사용합니다 .
  • 잠긴 스레드가 아닌 다른 스레드에서 잠금을 해제하려면 비 재귀 잠금 (또는 예외를 발생시키는 대신 명시 적으로 허용하는 재귀 잠금)을 사용해야합니다.
  • 당신이 사용하려는 경우 동기화 변수를 , 당신은 할 필요가 명시 적으로 뮤텍스 잠금을 해제 할 수 있는 동기화 변수를 기다리는 동안 자원이 다른 스레드에서 사용할 수 있도록 허용 그래서. 재귀 뮤텍스는 현재 함수의 호출자에 의해 이미 잠겼을 수 있기 때문에 비 재귀 뮤텍스 에서만 가능 합니다.

오늘 재귀 뮤텍스에 대한 필요성을 만났고 지금까지 게시 된 답변 중 가장 간단한 예라고 생각합니다. 이것은 두 개의 API 함수 인 Process (...) 및 reset ()을 노출하는 클래스입니다.

public void Process(...)
{
  acquire_mutex(mMutex);
  // Heavy processing
  ...
  reset();
  ...
  release_mutex(mMutex);
}

public void reset()
{
  acquire_mutex(mMutex);
  // Reset
  ...
  release_mutex(mMutex);
}

두 함수는 클래스의 내부를 수정하므로 동시에 실행해서는 안되므로 뮤텍스를 사용하고 싶었습니다. 문제는 Process ()가 내부적으로 reset ()을 호출하고, mMutex가 이미 획득 되었기 때문에 교착 상태가 발생한다는 것입니다. 대신 재귀 잠금으로 잠그면 문제가 해결됩니다.


재귀 뮤텍스를 사용하는 코드의 예를 보려면 Linux / Unix 용 "Electric Fence"의 소스를 참조하십시오. '그는 Valgrind 가 등장 하기 전에 해제 된 메모리를 사용하는 것뿐만 아니라 "경계 검사"읽기 / 쓰기 오버런과 언더런을 찾기위한 일반적인 Unix 도구 중 하나였습니다 .

Just compile and link electric fence with sources (option -g with gcc/g++), and then link it with your software with the link option -lefence, and start stepping through the calls to malloc/free. http://elinux.org/Electric_Fence


It would certainly be a problem if a thread blocked trying to acquire (again) a mutex it already owned...

Is there a reason to not permit a mutex to be acquired multiple times by the same thread?

ReferenceURL : https://stackoverflow.com/questions/2415082/when-to-use-recursive-mutex

반응형