본문 바로가기
게임개발/게임서버

교착 상태(Deadlock)

by do_ng 2023. 10. 17.

교착 상태란(Deadlock)?

한정된 자원을 둘 이상의 주체가 서로 동시에 사용하려고 대기할때 모든 작업의 진행이 멈춰버리는 현상

 

ThreadA는 공유자원 A를 점유한 상태로 공유자원 B를 점유하려고 요청했는데 ThreadB가 점유중이여서 대기하고 있는 상태이고 ThreadB는 공유자원 B를 점유한 상태로 공유자원 A를 점유하려고 요청했는데 ThreadA가 점유중이여서 서로 무한정 대기가 일어나는 상황이다.  

 

데드락 상황이 발생하는 코드)

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

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

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

            }            
        }
    }

    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 void Thread_1() {
            for (int i = 0; i < 100000; i++)
            {
                SessionManager.Test();
            }
        }

        static void Thread_2()
        {
            for (int i = 0; i < 100000; 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("종료");
        }
    }
}

 

어떻게 교착상태를 해결 할 수 있을까?

Lock을 획득하려는 시도를 몇 번 하다가 안되면 포기하고 다른 처리를 하는 방법은 어떨까?

Lock 획득이 불가능한 경우의 코드를 새롭게 짜야되고 프로젝트가 커질수록 구조도 매우 복잡하기 때문에 그러한 경우에 짜는 것도 매우 어렵고 데드락 상황이 발생했는지 모르고 넘어갈 수 있기 때문에 좋은 방법은 아님

 

 

데드락 상황이 발생했을 때 해결한 코드)

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

    Thread.Sleep(100);

    t2.Start();

    Task.WaitAll(t1, t2);

    Console.WriteLine("종료");
}

 

공유자원을 점유하는 순서를 지키도록 하면 이러한 문제를 해결 할 수 있다. 

첫번째 스레드가 실행되고 시간간격을 어느정도 두고 그 다음 스레드가 실행되는 방식으로 구현하면 공유자원에 접근하는 타이밍이 겹치지 않기 때문에 정상적으로 실행될 수 있음

 

 

 

 

 

'게임개발 > 게임서버' 카테고리의 다른 글

멀티 쓰레드 프로그래밍  (0) 2024.04.17
멀티쓰레드 Lock 구현 방식  (2) 2024.01.15
소켓 프로그래밍  (0) 2023.10.29
TLS(Thread Local Storage)  (0) 2023.10.28
ReadWriteLock  (0) 2023.10.26