C #의 재진입 잠금


119

다음 코드로 인해 .NET에서 C #을 사용하여 교착 상태가 발생합니까?

 class MyClass
 {
    private object lockObj = new object();

    public void Foo()
    {
        lock(lockObj)
        { 
             Bar();
        }
    }

    public void Bar()
    {
        lock(lockObj)
        { 
          // Do something 
        }
    }       
 }

6
이 질문의 제목을 변경하는 것을 고려할 수 있습니다. 이 제목은 사람들이 발견하지 못하도록 거의 디자인 된 것 같습니다.
Jeff Sternal

12
실제로 '재진입'이라는 검색어를 기반으로 이걸 찾았고 내 질문에 답했습니다.
중복

나는 @JeffSternal 코멘트에 동의합니다.이 질문은 질문을 검색하는 사람이 이미 "재진입"잠금에 익숙하다고 가정합니다. 또 다른 중복 질문은 내가 이것에 대한 좋은 제목이 있었다 생각 : stackoverflow.com/questions/3687505/...을
루이스 페레즈에게

답변:


148

아니요, 같은 물건을 잠그는 동안은 아닙니다. 재귀 코드는 효과적으로 이미 잠금 을 가지고 있으므로 방해받지 않고 계속할 수 있습니다.

lock(object) {...}Monitor 클래스 를 사용하는 약어입니다 . 으로 마크가 지적 , Monitor재진입 그래서 객체에 잠금 시도를 반복, 현재의 thread가 이미 잠금이있는 잘 작동됩니다.

다른 물체를 잠그기 시작 하면주의해야합니다. 다음 사항에 특히주의하십시오.

  • 항상 동일한 시퀀스에서 주어진 수의 개체에 대한 잠금을 획득합니다.
  • 잠금 을 획득하는 방법 과 반대 순서로 항상 잠금을 해제하십시오 .

이러한 규칙 중 하나를 위반하면 어느 시점에서 교착 상태 문제가 발생할 수 있습니다.

다음은 .NET의 스레드 동기화를 설명하는 좋은 웹 페이지입니다. http://dotnetdebug.net/2005/07/20/monitor-class-avoiding-deadlocks/

또한 한 번에 가능한 적은 수의 개체를 잠급니다. 가능하면 거친 잠금을 적용 하는 것이 좋습니다. 개체 그래프가 있고 해당 개체 그래프의 루트에 대한 잠금을 획득 할 수 있도록 코드를 작성할 수 있다면 그렇게하세요. 즉, 해당 루트 개체에 대해 하나의 잠금이 있으므로 잠금을 획득 / 해제하는 순서에 대해별로 걱정할 필요가 없습니다.

(참고로, 귀하의 예제는 기술적으로 재귀 적이 지 않습니다. 재귀 Bar()적이려면 일반적으로 반복의 일부로 자신을 호출해야합니다.)


1
특히 다른 시퀀스에서.
Marc Gravell

6
재귀; 과연; Guy의 이익을 위해 용어는 재진입
Marc Gravell

용어를 명확히 해주셔서 감사합니다. 질문을 수정하고 수정했습니다.
Guy

이 질문은 꽤 많은 관심을받는 것 같아서 처음 작성한 이후로 생각해온 몇 가지 다른 메모로 답변을 업데이트했습니다.
Neil Barnwell 2011

사실 잠금을 해제하는 순서는 중요하지 않다고 생각합니다. 선택하는 순서는 확실하지만 잠금을 해제하는 것이 조건이없는 한 (언제든지 해제 할 수 있음) 획득 한 모든 잠금을 해제하는 한 괜찮습니다.
bobroxsox 2014-06-12

20

글쎄, Monitor재진입을 허용하므로 스스로 교착 상태를 유지할 수 없습니다 ... 그래서 아니오 : 그렇게해서는 안됩니다.


7

스레드가 이미 잠금을 보유하고있는 경우 자체적으로 차단되지 않습니다. .Net 프레임 워크가이를 보장합니다. 두 개의 스레드가 코드 경로에 관계없이 순서에 상관없이 동일한 두 개의 잠금을 획득하려고 시도하지 않는지 확인하기 만하면됩니다.

동일한 스레드가 동일한 잠금을 여러 번 획득 할 수 있지만 잠금을 획득 한 횟수와 동일한 횟수만큼 잠금을 해제해야합니다. 물론이 작업을 수행하기 위해 "lock"키워드를 사용하는 한 자동으로 발생합니다.


모니터의 경우에는 해당되지만 반드시 다른 종류의 잠금은 아닙니다.
Jon Skeet

(물론 당신이 그것을 몰랐다는 것을 암시하고 싶지는 않습니다. – 단지 그것이 중요한 구별입니다. :)
Jon Skeet

그건 좋은 지적이야. 실제로 "잠금"을 "모니터"로 변경하려고했지만 산만 해졌습니다. 그리고 게으른. 그리고이 동작은 Windows 뮤텍스 커널 개체의 경우에도 마찬가지이므로 충분히 가깝다고 생각했습니다!
Jeffrey L Whitledge

5

아니요,이 코드에는 데드락이 없습니다. 정말로 교착 상태를 만들고 싶다면 가장 간단한 것은 최소한 2 개의 리소스가 필요합니다. 개와 뼈 시나리오를 고려하십시오. 1. 개는 1 개의 뼈를 완전히 제어 할 수 있으므로 다른 개는 기다려야합니다. 2. 2 개의 뼈를 가진 개 2 개는 각각 뼈를 잠그고 다른 뼈도 찾을 때 교착 상태를 생성하기 위해 최소한 필요합니다.

.. 등등 n 개의 개와 m 개의 뼈가 더 정교한 교착 상태를 유발합니다.

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