개인공부) 서버 실습(9) - DeadLock

Justin·2022년 5월 31일
0

서버공부

목록 보기
8/45
post-thumbnail

✅ 지난 시간 회고 및 새로운 개념

Monitor에 대한 개념을 시작으로 중간에 Exit을 해주지않아 DeadLock이 발생하는 상황을 만들고, 더 간결하게 코드 작성을할 수 있는 lock 개념에 대해 배웠다.

아주 간단한 DeadLock의 원인이었으니, 더 복잡한 케이스를 통해 배워볼 차례이다.

🔒자물쇠가 두 개인 경우 발생하는 DeadLock💀🔒

Key를 두 개 가지고 있어야 들어갈 수 있는 화장실이 있다고 가정했을 때, 2개의 화장실 이용자(쓰레드)가 각 한개씩 Key를 가지게 될 경우

서로 양쪽 Key를 홀딩하고 있는 상황이라 다른 이용자가 가져가지도 못하고, 본인 또한 이용하지도 못하며 서로 아무것도 못하는 DeadLock이 발생한다.

💯 해결방법

간단한 해결 방법으로는 규칙을 만들어주면된다. KEY 1 부터 접근해야 한다는 조건을 걸어주면 누구던지 KEY 1에 접근하고, 키를 홀딩하고 있기에 다른 이용자가 접근하지 못하며

이용자 A의 경우가 KEY1,2를 모두 가져 화장실을 이용할 수 있게된다.

🔳 실제 예시

    class PlaySection
    {
        static object key1 = new object();

        public static void Test()
        {
            lock (key1)
            {
                UserSection.UserAction();
            }
        }

        public static void PlayAction()
        {
            lock (key1)
            {
            }
        }

    }

    class UserSection
    {
        static object key2 = new object();

        public static void Test()
        {
            lock (key2)
            {
                PlaySection.PlayAction();
            }
        }
        public static void UserAction()
        {
            lock (key2)
            {
            }
        }
    }
    // 위 코드는 Task Start()를 통해 동작 시키고, 반복문에서 여러 번 작동하게 해둠

위와 같인 두 개의 Class에서 lock을 걸고, lock이 걸려 있는 다른 함수를 호출하는 과정을 서로 반복하며 위에서 언급했던 상황과 유사한 문제가 발생할 수 있다.

이해를 돕기 위한 설명
멀티 쓰레드 환경에서 보면 PlaySection.Test()UserSection.Test()가 거의 동시에 시작 되며 서로를 가지게 된다.

즉, 각자의 lock을 잡고 실행을 시키고자 하지만 PlaySection.Test()에서는 UserSection.UserAction()에 진입하고자 하는데 진입하기 위해서는 Key2가 필요하다.

근데 그 Key2는 UserSection.Test()가 잡고 PlaySection.PlayAction()에 진입하고자 한다. 이렇게 서로 lock 잡고 있어 다른 함수가 실행되지 못하는 상황에서 데드락이 발생하는 것이다.

💯 해결 방법

1. Monitor.TryEnter(Object, Timespan) 과 같이 타임아웃을 이용해 일정시간 동안 통과하지 못할 경우, 다른 행동을 하도록 구현하는 방법

  • 애초에 잘못되는 경우가 생긴다는게 코드 구현을 잘못했다 라는 것이고, 그걸 위해서 몇 라인을 더 사용한다는게 효율적인지 고민이 필요한 부분인 것 같다.

2. 접근할 때 일정 시간을 부여하는 것

사실 테스트 할 때 사용한 것과 같이 거의 동시에 쓰레드가 사용되는 경우는 잘 없다. 그렇기에 예시 처럼 거의 동시에 실행되고 있다면

Thread.Sleep() 으로 서로 잠시만 떨어지게 해두면 DeadLock 빠지지 않고 정상 종료 되는 걸 확인할 수 있다.

📒 결론

DeadLock은 QA중에도 잘 발생하지 않다가, 실제 트레픽이 늘어나며 원인을 발견하는 경우가 잦다고 한다. 미리 대비하는 것도 좋지만 어쩔 수 없는 경우에는 바로 원인을 파악하며 문제를 해결하는게 좋다고 할 수 있다.


오늘 정리

아직 DeadLock 상황이 발생할 정도로 구조를 만들고 작업 하는 일이 없이 간단한 예제 케이스만 보니, 큰 흐름은 알겠지만 자세하게는 감이 안온다.

아무튼 실무에서도 자주 발생하는 원인들이니 잘 기억해두어야겠다.

profile
인디 게임을 만들며 공부하고 있습니다.

0개의 댓글