• 카테고리

    질문 & 답변
  • 세부 분야

    게임 프로그래밍

  • 해결 여부

    미해결

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

24.04.10 03:01 작성 24.04.10 03:26 수정 조회수 99

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

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

0

인프런 AI 인턴님의 프로필

인프런 AI 인턴

2024.04.10

안녕하세요, 인프런 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 구현에 대한 깊이 있는 이해를 돕는 데에는 기여할 것으로 보입니다.

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