문제

POSIX는 뮤텍스가 재귀적일 수 있도록 허용합니다.이는 동일한 스레드가 동일한 뮤텍스를 두 번 잠글 수 있으며 교착 상태가 발생하지 않음을 의미합니다.물론 두 번 잠금을 해제해야 합니다. 그렇지 않으면 다른 스레드가 뮤텍스를 얻을 수 없습니다.pthread를 지원하는 모든 시스템이 재귀적 뮤텍스도 지원하는 것은 아니지만 원하는 경우 POSIX를 준수해야 합니다..

다른 API(더 높은 수준의 API)도 일반적으로 잠금이라고 불리는 뮤텍스를 제공합니다.일부 시스템/언어(예:Cocoa Objective-C)는 재귀적 및 비재귀적 뮤텍스를 모두 제공합니다.일부 언어는 둘 중 하나만 제공합니다.예:Java의 뮤텍스는 항상 재귀적입니다(동일한 스레드가 동일한 개체에 대해 두 번 "동기화"될 수 있음).그들이 제공하는 다른 스레드 기능에 따라 재귀 뮤텍스가 없어도 문제가 되지 않을 수 있습니다. 왜냐하면 스스로 쉽게 작성할 수 있기 때문입니다. (저는 이미 더 간단한 뮤텍스/조건 연산을 기반으로 재귀 뮤텍스를 직접 구현했습니다.)

내가 정말로 이해하지 못하는 것 :비재귀적 뮤텍스는 어디에 좋은가요?동일한 뮤텍스를 두 번 잠그는 경우 스레드 교착 상태가 발생하려는 이유는 무엇입니까?이를 피할 수 있는 고급 언어(예:교착 상태가 발생하는지 테스트하고 교착 상태가 발생하면 예외를 발생시킵니다) 일반적으로 그렇게 하지 않습니다.대신 스레드 교착 상태를 허용합니다.

이것은 실수로 두 번 잠그고 한 번만 잠금을 해제하는 경우에만 해당되며 재귀적 뮤텍스의 경우 문제를 찾기가 더 어렵기 때문에 대신 잘못된 잠금이 나타나는 위치를 확인하기 위해 즉시 교착 상태를 설정합니까?그러나 잠금을 해제할 때 잠금 카운터를 반환하는 것과 동일한 작업을 수행할 수 없고 마지막 잠금을 해제했는데 카운터가 0이 아닌 상황에서 예외를 발생시키거나 문제를 기록할 수 있습니까?아니면 내가 보지 못한 비재귀적 뮤텍스의 더 유용한 다른 사용 사례가 있습니까?아니면 비재귀적 뮤텍스가 재귀적 뮤텍스보다 약간 더 빠를 수 있기 때문에 단순한 성능일까요?그런데 제가 테스트해본 결과 그 차이는 그리 크지 않았습니다.

도움이 되었습니까?

해결책

재귀적 뮤텍스와 비재귀적 뮤텍스의 차이점은 소유권과 관련이 있습니다.재귀적 뮤텍스의 경우 커널은 재귀와 뮤텍스 간의 차이를 감지할 수 있도록 실제로 처음으로 뮤텍스를 얻은 스레드를 추적해야 합니다.대신 차단해야 하는 다른 스레드.또 다른 답변에서 지적했듯이 이 컨텍스트를 저장하기 위한 메모리와 이를 유지하는 데 필요한 주기 측면에서 추가 오버헤드에 대한 문제가 있습니다.

하지만, 여기에도 다른 고려 사항이 있습니다.

재귀 뮤텍스에는 소유권이 있으므로 뮤텍스를 잡는 스레드는 뮤텍스를 해제하는 스레드와 동일해야 합니다.비재귀적 뮤텍스의 경우 소유권 감각이 없으며 어떤 스레드가 원래 뮤텍스를 가져갔는지에 관계없이 일반적으로 모든 스레드가 뮤텍스를 해제할 수 있습니다.대부분의 경우 이러한 유형의 "뮤텍스"는 실제로 뮤텍스를 제외 장치로 사용할 필요는 없지만 두 개 이상의 스레드 간의 동기화 또는 신호 장치로 사용하는 세마포어 작업에 가깝습니다.

뮤텍스의 소유권과 함께 제공되는 또 다른 속성은 우선순위 상속을 지원하는 기능입니다.커널은 뮤텍스를 소유한 스레드와 모든 차단기의 ID를 추적할 수 있기 때문에 우선순위 스레드 시스템에서는 현재 뮤텍스를 소유한 스레드의 우선순위를 가장 높은 우선순위 스레드의 우선순위로 높이는 것이 가능합니다. 현재 뮤텍스를 차단하고 있습니다.이러한 상속은 이러한 경우에 발생할 수 있는 우선순위 역전 문제를 방지합니다.(모든 시스템이 이러한 뮤텍스에 대한 우선순위 상속을 지원하는 것은 아니지만 이는 소유권 개념을 통해 가능해지는 또 다른 기능입니다.)

클래식 VxWorks RTOS 커널을 참조하면 다음 세 가지 메커니즘을 정의합니다.

  • 뮤텍스 - 재귀를 지원하고 선택적으로 우선순위 상속을 지원합니다.이 메커니즘은 일관적인 방식으로 데이터의 중요한 섹션을 보호하는 데 일반적으로 사용됩니다.
  • 바이너리 세마포어 - 재귀 없음, 상속 없음, 단순 제외, 테이커와 제공자가 동일한 스레드일 필요는 없으며 브로드캐스트 릴리스가 가능합니다.이 메커니즘은 중요한 섹션을 보호하는 데 사용될 수 있지만 스레드 간의 일관된 신호 또는 동기화에도 특히 유용합니다.
  • 세마포어 계산 - 재귀 또는 상속이 없으며 원하는 초기 개수에서 일관된 리소스 카운터 역할을 하며 스레드는 리소스에 대한 순 개수가 0인 경우에만 차단됩니다.

다시 말하지만 이는 플랫폼에 따라 다소 다릅니다. 특히 이를 소위 말하는 것입니다. 그러나 이는 실행 중인 개념과 다양한 메커니즘을 대표해야 합니다.

다른 팁

정답은 ~ 아니다 능률. 비 반환 뮤텍스는 더 나은 코드로 이어집니다.

예 : a :: foo ()는 잠금을 얻습니다. 그런 다음 b :: bar ()를 호출합니다. 당신이 그것을 썼을 때 이것은 잘 작동했습니다. 그러나 나중에 누군가가 b :: bar ()를 변경하여 a :: baz ()를 호출하여 잠금 장치를 얻습니다.

글쎄, 당신이 재귀 적 뮤텍스가 없다면,이 교착 상태. 당신이 그것들을 가지고 있다면, 그것은 실행되지만 깨질 수 있습니다. A :: foo ()는 BAZ ()가 MUTEX를 획득하기 때문에 실행할 수 없다는 가정하에 Bar ()를 호출하기 전에 일관되지 않은 상태에 객체를 두었을 수 있습니다. 그러나 아마도 실행되지 않아야합니다! A :: foo ()를 쓴 사람은 아무도 A :: Baz ()를 동시에 호출 할 수 없다고 가정했습니다. 이것이 두 방법이 잠금을 취득한 전체 이유입니다.

Mutxes를 사용하기위한 올바른 정신 모델 : Mutex는 변하지 않는 것을 보호합니다. 뮤텍스가 유지되면 불변이 변할 수 있지만 뮤트를 방출하기 전에 불변량이 다시 설정됩니다. 재진입 자물쇠는 위험합니다. 두 번째로 자물쇠를 획득하면 불변이 더 이상 사실인지 확신 할 수 없기 때문에 위험합니다.

재진입 잠금 장치에 만족한다면, 이전에 이와 같은 문제를 디버깅 할 필요가 없었기 때문입니다. Java는 요즘 java.util.concurrent.locks에서 비 반환 잠금 장치를 가지고 있습니다.

Dave Butenhof 자신이 쓴대로:

"재귀 적 뮤텍스의 가장 큰 문제 중 가장 큰 문제는 잠금 체계와 범위를 완전히 잃어 버리도록 격려한다는 것입니다. 이것은 치명적입니다. 사악합니다."스레드 먹는 사람 "입니다. 당신은 가장 짧은 시간 동안 자물쇠를 보유하고 있습니다. 기간. 항상. 당신이 단순히 자물쇠가 붙잡고있는 것을 호출한다면, 당신이 그것을 알지 못하거나, Callee에 뮤텍스가 필요한지 알지 못하기 때문에 너무 오래 붙잡고 있습니다. 응용 프로그램에서 산탄 총을 목표로하고 방아쇠를 당기고 있습니다. 아마도 실을 사용하여 동시성을 얻기 시작했을 것입니다. 그러나 동시성을 방지했습니다. "

Mutxes를 사용하기위한 올바른 정신 모델 : Mutex는 변하지 않는 것을 보호합니다.

왜 이것이 Mutxes를 사용하기에 실제로 올바른 정신 모델인지 확신합니까? 올바른 모델은 데이터를 보호하지만 불변량은 아니라고 생각합니다.

불변량을 보호하는 문제는 단일 스레드 애플리케이션에서도 나타나며 멀티 스레딩 및 뮤 테스와 공통적 인 것이 없습니다.

또한 불변량을 보호 해야하는 경우 여전히 바이너리 세마포어를 사용할 수 있습니다.

재귀 뮤 텍스가 유용한 주된 이유 중 하나는 동일한 스레드에 의해 메소드에 여러 번 액세스하는 경우입니다. 예를 들어, Mutex Lock이 은행 A/C를 철회 할 수있는 경우 해당 철수와 관련된 수수료가 있으면 동일한 Mutex를 사용해야합니다.

재귀 뮤 텍스의 유일한 유용 사례는 객체에 여러 방법이 포함 된 경우입니다. 메소드 중 하나라도 객체의 내용을 수정하므로 상태가 다시 일관되기 전에 객체를 잠그십시오.

메소드가 다른 메소드를 사용하는 경우 (예 : addnewarray () 호출 addnewpoint ()을 호출하고 recheckbounds ()로 마무리되지만 해당 함수는 자체적으로 뮤트를 잠그면 필요합니다. 그런 다음 재귀 뮤트는 상생입니다.

다른 경우 (나쁜 코딩 만 해결하고, 다른 객체에서도 사용하는 경우) 분명히 잘못된 것입니다!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top