[C# 서버] Lock 기초

Yerin·2023년 9월 19일

C# 게임 서버

목록 보기
6/13

Monitor

Monitor 키워드를 이용해 해당 행위를 끝날 때까지 작업을 보장해준다.

namespace SeverCore
{
    class Program
    {
        static int number = 0;
        static object _obj = new object();

        static void Thread_1()
        {

            for (int i = 0; i < 100000; i++) 
            {
                // 상호배제 Mutual Exclusive
                Monitor.Enter(_obj); // 문을 잠구는 행위
                number++;
                Monitor.Exit(_obj); // 잠금을 풀어준다.
            }
                

        }


        static void Thread_2()
        {
            for (int i = 0; i < 100000; i++)
            {
                Monitor.Enter(_obj);
                number--;
                Monitor.Exit(_obj);
            }
        }

        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);
        }
    }
}

하지만 아래와 같이 Monitor.Enter()를 사용 후 Monitor.Exit()를 제대로 맞춰주지 않으면
데드락 (DeadLock) 현상이 발생한다.

            for (int i = 0; i < 100000; i++) 
            {
                // 상호배제 Mutual Exclusive
                Monitor.Enter(_obj); // 문을 잠구는 행위
                {
                	number++;
                    return;
                }
                Monitor.Exit(_obj); // 잠금을 풀어준다.
            }

Monitor.Exit() 를 사용할 타이밍을 잡는 것이 조금 어려울 수 있다.

일반적인 상황에서는 이를 try ~ catch를 이용하여 해결한다.

for (int i = 0; i < 100000; i++) 
            {
                // 상호배제 Mutual Exclusive
                try
                {
                    Monitor.Enter(_obj); // 문을 잠구는 행위
                    number++;
                }
                finally
                {
                    Monitor.Exit(_obj); // 잠금을 풀어준다.
                }
            }

하지만 이도 번거롭다고 느낄 수 있기 때문에
lock이라는 키워드를 사용한다.

lock

잠그고 여는 행위를 lock 키워드로 한번에 진행하는 것이다.
DeadLock을 조금이라도 줄일 수 있는 유용한 방법이다.

namespace SeverCore
{
    class Program
    {
        static int number = 0;
        static object _obj = new object();

        static void Thread_1()
        {

            for (int i = 0; i < 100000; i++) 
            {
                // 상호배제 Mutual Exclusive
                lock (_obj)
                {
                    number++;
                } 
            }
        }

        static void Thread_2()
        {
            for (int i = 0; i < 100000; i++)
            {
                lock (_obj)
                {
                    number--;
                }
            }
        }

        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);
        }
    }
}
profile
재밌는 코딩 공부

0개의 댓글