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

Running boy님의 프로필 이미지
Running boy

작성한 질문수

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

ReaderWriterLock 구현 연습

ReaderWriterLock은 반드시 재귀적으로 호출되어야 하나요?

해결된 질문

작성

·

225

·

수정됨

0

만약 한 쓰레드에서 ReadLock과 WriteLock이 전부 호출된다고 했을 때 반드시 호출의 역순으로 Unlock을 호출해야 되나요?

 

아래는 C#에 구현돼있는 ReaderWriterLockSlim 클래스를 사용하여 실행한 예시입니다.

class Program
{
    static ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);

    static void Main(string[] args)
    {
        Task.WaitAll(
            Task.Run(() =>
            {
                _lock.EnterWriteLock();
                _lock.EnterReadLock();
                Thread.Sleep(5000);
                _lock.ExitWriteLock();
                _lock.ExitReadLock();
            }));
    }
}

WriteLock -> ReadLock -> WriteUnlock -> ReadUnlock 순으로 호출했고 정상적으로 작동합니다.

강의에서 구현한 ReaderWriterLock을 사용해도 예외가 발생하지는 않습니다만 위의 순서로 호출하면 flag가 엉망이 됩니다.

public void WriteUnlock()
{
    int lockCount = --_writeCount;
    if (lockCount == 0)
        Interlocked.Exchange(ref _flag, EMPTY_FLAG);
}

동일한 쓰레드가 ReadUnlock을 호출하지 않은 상태에서(즉 read count가 0이 아닌 상태에서) WriteUnlock을 호출할 경우 flag가 0으로 초기화되기 때문에 이후에 ReadUnlock을 호출할 경우 flag가 -1로 초기화됩니다.

 

제가 생각하기엔 굉장히 특이한 케이스고 실제로 함수가 재귀적으로 호출되기 때문에 발생할 일은 없다고 보는데요...혹시라도 휴먼에러로 위와 같은 상황이 벌어질 경우를 대비해서 예외를 추가하거나 WriteUnlock 로직을 수정해서 'EMPTY_FLAG'가 아닌 '_flag & READ_MASK'를 대입하면 어떤가요?

답변 2

0

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

너무 극단적인 케이스고, 사실 락 순서를 저렇게
해제하는 상황이라면 그냥 크래시를 내는게 맞다고 봅니다 ㅎㅎ!

0

안녕하세요, 인프런 AI 인턴입니다.

wjdgh9577님께서 질문하신 내용은 ReaderWriterLock의 재귀적 호출과 관련하여 특정 호출 순서에서의 flag 처리 방법에 대한 것입니다. ReadLock과 WriteLock을 호출한 후, 이들을 역순으로 Unlock하는 과정에서 발생할 수 있는 flag 값의 비정상적 변화에 대한 문제를 지적하며, 이를 해결할 수 있는 방법에 대해 질문하셨습니다.

질문에서 언급한 상황은 실제로 멀티쓰레딩 환경에서 중요한 고려사항이 될 수 있으며, 특히 게임 서버와 같은 응용 프로그램에서는 다양한 쓰레드가 자원에 동시에 접근하려 할 때 올바른 동기화 메커니즘이 매우 중요합니다.

직접적으로 wjdgh9577님의 상황에 해당하는 답변이 제 기존 자료에 명시되어 있지는 않지만, ReaderWriterLock 구현과 관련해 일반적인 질의응답을 찾아볼 수 있었습니다.

예를 들어, WriteUnlock() 구현과 관련한 질문에서 다룬 내용이 유사한 문맥에서 도움이 될 수 있습니다:
- WriteUnlock() 질문드립니다.
- 이 질문에서는 WriteUnlock() 함수 내부에서 Interlocked.Exchange를 사용하여 _flagEMPTY_FLAG로 설정하는 과정에 대해 질문되었습니다. 질문자와 강사 모두 단순 대입을 통해 _flag 값을 수정해도 되는지에 대한 의문을 제기하였으며, 강사는 대입이 항상 원자적인 것이 아니라는 점을 지적하면서, 특정 상황에서 Interlocked.Exchange 사용의 정당성에 대해 설명했습니다.

wjdgh9577님의 경우, 재귀적으로 호출되는 상황에서의 더 복잡한 논의가 필요할 것으로 보입니다. 질문에서 언급한 “WriteUnlock 로직을 수정해서 ‘EMPTY_FLAG’가 아닌 ‘_flag & READ_MASK’를 대입”하는 방법을 포함하여, 다양한 경우의 수와 이에 대한 처리 방법에 대한 논의가 필요해 보입니다.

현재 제공된 기존 답변들이 wjdgh9577님의 질문에 직접적인 해결 방안을 제시하지는 않을 수 있으나, ReaderWriterLock 구현에 대한 깊이 있는 이해를 돕는 데에는 기여할 것으로 보입니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

Running boy님의 프로필 이미지
Running boy

작성한 질문수

질문하기