인프런 커뮤니티 질문&답변

wocl00님의 프로필 이미지
wocl00

작성한 질문수

[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버

DeadLock

수업의 코드가 이해가 안되어서 질문드립니다.

작성

·

265

0

Thread1이 TestUser에서 lock이 걸리고 

public static void TestUser()

        {

            lock(_lock)  <-- 요기 

            {

                Console.WriteLine("This is TestUser");

            }

        }

Thread2가 TestSession에서 lock이 걸리는 걸로 알고 있습니다.

        public static void TestSession()

        {

            lock(_lock)

            {

                Console.WriteLine("This is TestSession");

            }

        }

 

 

 

근데 이렇게 해서 데드락이 걸린다는 게 잘 와닿지 않습니다. 

 

수업시간에 2개의 자물쇠를 각각 다른 사람이 잠굴 때 데드락이 발생한다고 하셨는데 위 코드가 그것을 설명하는 내용인가요? 

 

TestUser에서 lock이 걸려도 lock안의 코드를 수행하고 나오고, TestSession에서도 lock안의 코드를 수행하고 나오면 되지 않나요? 

 

서로 다른 쓰레드여도 작업하는 공간이 다를텐데 왜 둘다 lock에서 먹통이 되는지 잘 이해가 가지 않습니다. 

답변 1

1

Rookiss님의 프로필 이미지
Rookiss
지식공유자

수업시간에 2개의 자물쇠를 각각 다른 사람이 잠굴 때 데드락이 발생한다고 하셨는데 위 코드가 그것을 설명하는 내용인가요? 

TestUser에서 lock이 걸려도 lock안의 코드를 수행하고 나오고, TestSession에서도 lock안의 코드를 수행하고 나오면 되지 않나요? 

네 말씀하신게 맞습니다.
그런데 예제의 케이스는 [각각 lock을 걸고 푸는] 케이스가 아닙니다. 
lock이 2개 있는 상태에서,
쓰레드A는 [1번을 걸고 - 풀지 않은 상태에서 2번을 걸고]
쓰레드 B는 반대로 [2번을 걸고- 풀지 않은 상태에서 1번을 거는] 예제입니다.
매우 중요한 부분이니 이해가 가실 때까지 영상을 반복해서 보시기 바랍니다.

wocl00님의 프로필 이미지
wocl00
질문자

1. 쓰레드A는 [1번을 걸고 - 풀지 않은 상태에서 2번을 걸고]

쓰레드 B는 반대로 [2번을 걸고- 풀지 않은 상태에서 1번을 거는] 예제입니다.

 

여기서 말하는 1번과 2번은 무엇인가요? 

SessionManger._lock 과 UserManager._lock 인가요??

 

2. 

그렇다면 SessionManger._lock을 _lock_session 

UserManager._lock을 _lock_user라고 한다면, 

 

Thread_1 에서 SessionManger.Test를 호출할 때 _lock_session을 사용해서 Lock을 걸고 

이때 동시에 Thread_2 는 UserManger.Test를 호출해서 _lock_user를 사용해서 Lock을 겁니다. 

 

Thread_1은 SessionManger.Test를 통해 UserManger.TestUser를 호출할 때 _lock_user로 Lock을 걸어야 합니다. 근데 Thread_2에서 _lock_user를 사용하고 있다보니까 Lock을 걸 수 없고 

마찬가지로, Thread_2 역시 UserManger.Test를 통해 SessionManager.TestSession을 호출할 때 _lock_session으로 Lock을 걸어야 하는데 Thread_1에서 이미 사용하고 있다보니 Lock을 걸 수 없어서

데드락이 발생합니다.

라고 이해했는데 제가 이해한 바가 맞는건가요? 어떤 부분이 틀렸는지 알려주시면 감사하겠습니다. 

 

 

<참고 - 코드> 

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

        public static void TestSession()
        {
            lock(_lock_session)
            {
                Console.WriteLine("This is TestSession");
            }
        }

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

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

        public static void TestUser()
        {
            lock(_lock_user)
            {
                Console.WriteLine("This is TestUser");
            }
        }

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

    class Program
    {
            

        static int number = 0;
        static object _obj = new object(); 

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

        static void Thread_2()
        {
            for(int i=0; i<100; 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("데드락에 걸리지 않았다!");
        } 

} 

Rookiss님의 프로필 이미지
Rookiss
지식공유자

네 잘 이해하셨고 1,2의 의미도 그게 맞습니다.

wocl00님의 프로필 이미지
wocl00

작성한 질문수

질문하기