더북(TheBook)

특히 두 번째 문제가 심각합니다. 다음 코드를 예로 들어 볼게요.

코드 지나치게 자잘한 임계 영역

class Player
{
    CriticalSection m_positionCritSec;
    Vector3 m_position;  // ➊
    CriticalSection m_nameCritSec;
    string m_name;       // ➋
    CriticalSection m_hpCritSec;
    int m_hp;            // ➌
}

 

각 클래스의 멤버 변수마다 뮤텍스를 두었습니다. 이 변수들을 무조건 ~ 순서로 액세스한다는 규칙을 지키면서 코딩해야만 교착 상태를 피할 수 있습니다. 프로그램이 구구단 수준으로 단순하면 몰라도 크기가 커진다면 자꾸만 증가하는 규칙을 감당하기가 어렵습니다. 프로그램의 실행 성능도 중요하지만, 더 중요한 것은 여러분 시간입니다.

뮤텍스는 어느 정도 굵직하게 잠금 범위를 잡아야 합니다. 그렇다고 범위를 너무 넓게 잡으면 안 됩니다. 극단적인 예이지만, 프로그램 내부의 전체 데이터를 한꺼번에 보호하는 뮤텍스가 단 하나만 있으면 어떻게 될까요? 프로그램의 각 함수는 그 큰 뮤텍스를 잠가야 합니다. 그러면 싱글스레드로 작동하는 프로그램과 다를 바가 없습니다.

그래서 뮤텍스 범위는 적당히 넓게 나누는 것이 좋습니다. 동시에(여러 CPU가 병렬로) 연산하면 유리한 부분은 잠금 단위를 나누고, 병렬로 하지 않아도 별로 성능에 영향을 주지 않는 부분들은 잠금 단위를 나누지 않는 것이 좋습니다. 게임 서버를 멀티스레드 구조로 만들 경우 어디를 잠금 단위로 하는 것이 좋을지는 1.11절에서 설명하겠습니다.

교착 상태가 무엇인지부터 알아봅시다.

Note ≣ 컨텐션(Contention)이란?

두 스레드가 동시에 한 데이터를 액세스하려고 하는 상황을 의미합니다. 두 스레드 중 하나 이상이 읽기 또는 쓰기를 할 때 뮤텍스로 잠금을 해서 보호하지 않으면 경쟁 상태가 발생하는 문제가 생깁니다. 또 뮤텍스로 잠금을 할 때는 한 스레드가 일을 하는 동안 다른 스레드가 모두 대기를 함으로써 병렬성이 사라지는 문제가 생깁니다. 컨텐션은 멀티스레드 프로그래밍에서 불가피합니다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.