개인공부) 서버실습(14) - ReaderWriterLock 개념

Justin·2022년 6월 6일
0

서버공부

목록 보기
13/45
post-thumbnail

✅ 지난 시간

지난 시간에 Auto, Manual, Mutex를 통한 Event 형식의 lock 구조에 대해 배웠다. Event 형식의 특징은 관리자(커널) 영역에 작업이 필요하기에

Context Switching이 발생하여 구동이 느리기에 빠른 작업이 필요한 곳에는 적절하지 않다고 정리했다. 오늘은 간단하게 그동안 배운 것에 대해 복습을 하고 넘어가는 시간이다.

📝 복습

세가지 구조

lock의 세가지 구조를 요약하자면 아래와 같다.

  • 근성: 계속 빙글뱅글 lock을 돌며 대기하는 것
  • 양보: 잠시 쉬었다가 다시 와서 획득 시도 하는 것
  • 갑질: 관리자를 시켜 알려달라 요구하는 것

상황마다 적절하게 사용해야 한다
그동안 배웠던 lock은 어떤게 무조건 좋다. 라는 개념이 아니라 각자 적절한 상황에서 사용하거나, 혼합해서 사용한다.

그동안 사용했던 lock

◼ lock
내부적으로 Monitor Class 를 사용하여 편리하게 사용 가능한 lock -> (상호배제: 나만 들어가고 문 잠구는 것)

        static object key = new object();

        static void Main(string[] args)
        {
            lock(key)
            {

            }
        }

◼ SpinLock
기존에는 While, Interlocked 등을 사용하여 SpinLock을 구현했으나, C# 에서는 이렇게 간단히도 구현가능하니 사용해보면 된다. -> (상호배제: 나만 들어가고 문 잠구는 것)

        static SpinLock spin = new SpinLock();
        static bool lockTaken;

        static void Main(string[] args)
        {
            try
            {
            // lock이 성공할 경우 lockTaken 을 true로 변경
                spin.Enter(ref lockTaken);
            }
            // 정상적으로 Exit이 안될 경우를 위한 예외처리
            finally
            {
	            if (lockTaken)
    	            spin.Exit();
            }
        }

◼ Mutex
느리지만 별도의 프로그램 끼리 동기화 할 때 사용하기 적절하다. 하지만 실시간 MMORPG의 경우는 적절한 방법이 아니기에 많이 사용되지 않는다.

◼ 그외에 직접 만드는 방법도 있다.
처음 배울 때는 직접 만들고, 익숙해지면 있는걸 사용하는 방안을 추천

코어 멀티 쓰레드, 콘텐츠 멀티 쓰레드?
핵심 코어만 멀티 쓰레드를 할 것인지, 게임 콘텐츠도 멀티 쓰레드를 사용할 것인지 정해야할 때가 온다.

콘텐츠도 멀티 쓰레드로 할 경우 난리도가 엄청 올라감. 경계가 적은 심리스를 구현할 때는 멀티 쓰레드를 사용하기도 함.

바람의 나라, 뮤 같이 갈 수 있는 지역이 구분되고, 공간안에서 따로 구동이 가능할 때는 싱글 쓰레드를 사용하기도 한다.


💫 Reader Writer Lock 개념

개요
게임에서 이벤트를 통해 Reward를 제공하는 코드가 있고, 운영자가 나중에 Reward를 추가할 수 있는 구조로 만든다고 가정한다.
그렇게 되면 Reward를 찾고, 추가하는 과정(Write)에서 멀티 쓰레드의 문제가 생길 수 있기에 lock이 추가 되어야한다.

class Reward
        {
        } 
        static Reward GetRewardByID(int id)
        {
            lock (key)
            {
            }
            return null;
        }

⭕ 개선하고 싶은 사항

위와 같은 상황이라면 리워드를 추가하는 경우는 매우 적기 때문에 그러한 상황을 위해서 lock을 걸어 놓는다는 것이 아쉽다.

이때 읽을 때(Read)는 lock 없는 것 처럼 자유롭게 다니고, 추가할 때(Write)는 lock을 통해 해야 하는 구조로 사용하면 효율적이고 예쁜 구조가 될 수 있다.

우선 EnterReadLock(), ExitReadLock() 처리를 해두면 WriteLock에서 잡아둔게 없는 순간에는 lock이 없는 것 처럼 자유롭게 다닐 수 있게 된다.

만약 추가할 때 EnterWriteLock(), ExitWriteLock() 에서 잡게 된다면 Read 영역에서는 통과를 하지 못하는 상황이 된다.

+추가로 WriteLock을 시도하는 시점에 Read에 접근한다면 WriteLock을 잡지 않고, Read가 끝날 때 까지 대기한다.

💨 오늘의 마무리

lock은 왜 사용하는지, 어떤 lock의 구조가 있는지에 대해서는 지식이 쌓인거 같다. 이제 실습을 통해 구조를 직접 제작해보고 싶은 마음이 든다.

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

0개의 댓글