티스토리 뷰

멤버 함수가 멤버 변수들을 수정하지 않는다면 const 로 선언하는 것이 자연스럽다. 그런데 스레드를 사용한다면 문제가 생길 수 있다. 예시를 통해 살펴보자.

mutex의 사용

다음은 다항식의 근을 구는 함수 roots 를 구현하는 상황이다. 성능 향상을 위해 캐싱을 이용하였으며, rootsAreValid 의 값을 이용하여 캐싱 여부를 판별하는 함수이다.

class Polynomial {
public:
    using RootsType = std::vector<double>;
    
    RootsType roots() const
    {
        if(!rootsAreValid) {
            ...
            rootsAreValid = true;
        }
    }
    
private:
    mutable bool rootsAreValid{ false };
    mutable RootsType rootVals{};
};

 그런데 여기서 두 개의 스레드가 roots 함수를 호출하는 경우를 생각해보자. rootsAreValidrootVals 은 스레드에 안전하지 않기 때문에 mutex 를 써야만 한다. 문제는 roots 함수가 const 함수이기 때문에 mutex 또한 mutable 로 선언해야만 한다.

class Polynomial {
public:
    using RootsType = std::vector<double>;
    
    RootsType roots() const
    {
        std::lock_guard<std::mutex> g(m);
        if(!rootsAreValid) {
            ...
            rootsAreValid = true;
        }
    }
    
private:
    mutable std::mutex m;
    mutable bool rootsAreValid{ false };
    mutable RootsType rootVals{};
};

 mutex 를 추가함으로써 이제 Polynomial 객체는 복사와 이동이 불가능해져버렸다.

atomic의 사용

 mutex 를 대신하여 atomic 을 사용하는 경우에도 문제가 발생 할 수 있다. 아래와 같은 예제를 보자.

class Widget {
public:
    ...
    int magicValue() const
    {
        if (cacheValid) return cachedValue;
        else {
            auto val1 = expensiveComputation1();
            auto val2 = expensiveComputation2();
            cachedValue = val1 + val2;
            cacheValid = true;
            return cachedValue;
        }
    }
private:
    mutable std::atomic<bool> cacheValid{ false };
    mutable std::atomic<int> cachedValue;
};

 atomic 사용함으로써 이제 스레드에는 안전해졌다. 그런데 문제는 동시에 여러개의 스레드가 magicValue() 에 접근하게 되면 비싼 계산을 하는 두 개의 함수들을 모든 스레드가 사용하게 된다. 이는 성능적으로 큰 영향을 끼치게 된다. 이를 막기 위해서는 결과적으로 mutex 를 사용할 수 밖에 없다.

결론

 const 멤버 함수는 스레드 환경에서 적절하지 않는 경우가 많다. 현재 스레드에 안전하더라도 앞으로 어떻게 될지 모르기 때문에 언제라도 스레드 환경에 노출될 수 있다는 가정을 하고 작성해야만 한다. const 멤버 함수를 정의하기 전에 항상 주의하도록 하자.

 

참고 서적

스콧 마이어스, Effective Modern C++
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함