데드락

Eunho Bae·2022년 2월 24일
0

두 개 이상의 작업이 서로 상대방의 작업이 끝나기 만을 기다리고 있기 때문에 결과적으로 아무것도 완료되지 못하는 상태를 가리킨다.


코드

class SessionManager
   {
       static object _lock = new object();

       public static void TestSession()
       {
           lock (_lock) // t2 쓰레드가 열쇠가 없어서 못들어가는 곳
           {

           }
       }

       public static void Test()
       {
           lock(_lock)
           {
               UserManager.TestUser();        
           }
       }
   }

   class UserManager
   {
       static object _lock = new object();

       public static void TestUser()
       {
           lock(_lock) // t1 쓰레드가 열쇠가 없어서 못들어가는 곳
           {

           }
       }

       public static void Test()
       {
           lock(_lock)
           {
               SessionManager.TestSession();
           }
       }
   }

   internal class Program
   {
       static void Thread1()
       {
           for (int i = 0; i < 100000; i++)
               SessionManager.Test();
       }

       static void Thread2()
       {
           for (int i = 0; i < 100000; i++)
               UserManager.Test();
       }
       
       static void Main(string[] args)
       {
           Task t1 = new Task(Thread1);
           Task t2 = new Task(Thread2);
           t1.Start();
           t2.Start();

           Task.WaitAll(t1, t2);
       }
   }

코드 설명

각각의 클래스에 존재하는 _lock 변수를 열쇠라고 생각하고, lock(_lock) 부분을 문고리라고 생각하자.
위 코드에서 두 개의 쓰레드가 각각 SessionManager와 UserManager 클래스의 Test() 함수를 호출하고 있다. 먼저 Thread1(즉 t1 쓰레드)가 SessionManager의 집에 있는 _lock이라는 하나밖에 없는 열쇠를 집어들고 lock()이라는 문고리의 열쇠구멍에 넣어서 lock(_lock)이 되었다고 생각하자. 그러면 열쇠가 열쇠구멍에 넣어졌기 때문에 문이 열릴 것이고 UserManager.TestUser()를 호출할 것이다. 이때 t1 쓰레드와 동시에 t2 쓰레드도 t1와 똑같은 행동을 할 것이기 때문에 결과적으로 t2도 SessionManager.TestSession()를 호출할 것이다.

하지만 t1이 이미 SessionManager의 _lock이라는 열쇠를 가져가서 열쇠구멍에 쑤셔넣어 문을 여는데 사용을 했기 때문에(현재 SessionManager의 Test() 함수에 있는 열쇠구멍에 꽂혀있는 상태임) 열쇠가 없어서 TestSession() 함수의 lock(_lock) 부분만 멍하니 쳐다보게 될 것이다. (t1도 이미 t2가 열쇠를 써버렸기 때문에 없는건 마찬가지)

번외

아래는 내가 데드락을 잘 이해하고 있는 것이 맞는지 테스트한 코드이다. 동시에 들어가서 일어난 문제이니 호출횟수를 10회로 줄이고 t1이 열쇠를 다 쓰고 반납한 후에 시간을 좀 두고 t2 쓰레드를 동작시켰다.

profile
개인 공부 정리

0개의 댓글

관련 채용 정보