서버/서버 이론

데드락 (DeadLock)

잼잼재미 2025. 3. 28. 00:14

데드락 (DeadLock)


데드락(Deadlock)은 컴퓨터 과학에서 여러 프로세스나 스레드가 서로를 무한히 기다리는 상태를 말한다. 이 상태에서는 모든 관련 프로세스나 스레드가 정지 상태에 빠져, 작업을 계속할 수 없게 된다.

 

ex) 화장실에는 두개의 자물쇠가 있다고 가정. 서로 다른 사람이 각각 하나의 자물쇠를 가지면 둘다 잠글 수 없는 데드락 상태가 발생한다. 그래서 1번 자물쇠부터 가지고, 2번 자물쇠를 가지도록 약속을 해야한다. 

 

 

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

        public static void TestSession()
        {
            lock (_lock)
            {

            }
        }

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

    class UserManager
    {
        static object _lock = new object ();
        public static void Test()
        {
            lock (_lock)
            {
                SessionManager.TestSession();
            }
        }

        public static void TestUser()
        {
            lock ( _lock)
            {

            }
        }
    }
    internal class Program
    {
        static int number = 0;
        static object _obj = new object();

        static void Thread_1()
        {
            for (int i = 0; i < 10000; i++)
            {
                SessionManager.Test();
            }
        }

        static void Thread_2()
        {
            for (int i = 0; i < 10000; i++)
            {
                UserManager.Test();
            }
        }

        static void Main(string[] args)
        {
            Task t1 = new Task(Thread_1);
            Task t2 = new Task(Thread_2);

            t1.Start();
            t2.Start();

            Task.WaitAll(t1, t2);

            Console.WriteLine(number);
        }
    }
}

 

 

이번에는 두개의 쓰레드에서 Lock을 사용하는 예제이다.

 

  • Thread_1 : SessionManager.Test()를 호출 ->  SessionManager의 락을 획득 -> 그 안에서 UserManager.TestUser()를 호출 ->  UserManager.TestUser()는 UserManager의 락을 획득하려고 함
  • Thread_2 :  UserManager.Test()를 호출 -> UserManager의 락을 획득 -> 그 안에서 SessionManager.TestSession()을 호출 ->  SessionManager.TestSession()는 SessionManager의 락을 획득하려고 함

이 시점에서 데드락이 발생할 수 있다. 만약 Thread_1이 SessionManager의 락을 획득하고 UserManager의 락을 기다리는 동안, Thread_2가 UserManager의 락을 획득하고 SessionManager의 락을 기다린다면, 두 스레드는 서로가 가진 락을 기다리며 무한정 대기하게 된다.

 

 

데드락 해결 방법

static void Main(string[] args)
{
    Task t1 = new Task(Thread_1);
    Task t2 = new Task(Thread_2);

    t1.Start();

    Thread.Sleep(1000);	// 시간차

    t2.Start();

    Task.WaitAll(t1, t2);

    Console.WriteLine(number);
}

 

Lock을 획득하는 순서를 일관되게 유지할 수 있도록 Thread간 시간차를 준다.

 

 

※ 데드락은 개발하는 단계에서 발견되는 것 보다, 유저들이 많이 이용하는 라이브 서비스 중, 많이 발생한다. 데드락은 미리 예방하기보다는 크러쉬가 나면 그 후에 데드락이 발생한 위치를 찾고 문제를 해결하는 것이 더욱 간단할 수 있다.

'서버 > 서버 이론' 카테고리의 다른 글

Lock 구현  (0) 2025.03.29
Lock  (0) 2025.03.27
InterLocked  (0) 2025.03.24
메모리 배리어  (0) 2025.03.19
캐시 이론  (0) 2025.03.18