programing

중첩된 잠금으로 인해 교착 상태가 발생하지 않는 이유는 무엇입니까?

padding 2023. 7. 17. 20:43
반응형

중첩된 잠금으로 인해 교착 상태가 발생하지 않는 이유는 무엇입니까?

왜 이 코드는 교착 상태를 일으키지 않습니까?

   private static readonly object a = new object();

...

   lock(a)
   {
      lock(a)
      {
         ....
      }
   }

스레드가 이미 잠금을 보유하고 있으면 문제 없이 다시 "잠금"할 수 있습니다.


그 이유에 대해, (그리고 그것이 좋은 생각인 이유에 대해) a -> b 프로그램의 다른 곳에 정의된 잠금 순서가 있는 다음 상황을 고려합니다.

void f()
{
    lock(a)
    { /* do stuff inside a */ }
}

void doStuff()
{
    lock(b)
    {
        //do stuff inside b, that involves leaving b in an inconsistent state
        f();
        //do more stuff inside b so that its consistent again
    }
}

이런, 우리는 방금 우리의 잠금 명령을 위반했고 우리의 손에 잠재적인 교착 상태에 빠졌습니다.

우리는 정말로 다음과 같은 일을 할 수 있어야 합니다.

function doStuff()
{
    lock(a)
    lock(b)
    {
        //do stuff inside b, that involves leaving b in an inconsistent state
        f();
        //do more stuff inside b so that its consistent again
    }
}

전화를 걸 때 자동으로 잠금 해제되지 않고 잠금 순서를 유지할 수 있습니다.f().

lock키워드는 재인식 잠금을 사용합니다. 즉, 현재 스레드가 이미 잠금을 가지고 있으므로 재인식을 시도하지 않습니다.

다음과 같은 경우 교착 상태가 발생합니다.

스레드 1이 잠금 A를 획득합니다.
스레드 2가 잠금 B를 획득합니다.
스레드 1은 잠금 B(스레드 2가 완료될 때까지 대기)를 획득하려고 시도하고 스레드 2는 잠금 A(스레드 1이 완료될 때까지 대기)를 획득하려고 시도합니다.

이제 두 스레드가 서로 대기 중이므로 교착 상태에 빠집니다.

C# 언어 사양의 섹션 8.12부터:

상호 제외 잠금이 유지되는 동안 동일한 실행 스레드에서 실행되는 코드도 잠금을 가져오고 해제할 수 있습니다.그러나 다른 스레드에서 실행되는 코드는 잠금이 해제될 때까지 잠금을 얻지 못하도록 차단됩니다.

내부적으로 볼 때,lock스코프가 외부와 동일한 스레드에 있습니다.

언급URL : https://stackoverflow.com/questions/5035126/why-do-nested-locks-not-cause-a-deadlock

반응형