안녕하세요,
재재입니다.

지난 포스팅에서 각 mutex 종류별 특징을 알아봤습니다.

이번 포스팅에선,
c++ recursive_mutex 활용하기를 준비했습니다.

(1) std::recursive_mutex 란?

c++ std::recursive_mutex 는
일반적으로 사용하는 std::mutex 와는 다르게,
하나의 thread 내에서 동일한 뮤텍스에 대해 잠그는 것을 (재귀적으로) 여러번 할 수 있습니다.

여기서 핵심은 std::recursive_mutex가 재귀적으로 잠금 (lock) 을 허용한다는 것이고,
unlock() 또한 같은 횟수만큼 호출해야 합니다.

https://en.cppreference.com/w/cpp/thread/recursive_mutex

(2) std::recursive_mutex 사용 시기

c++ std::recursive_mutex 를 사용하는 시점은,
생각보다 많지 않은 경우에서 쓰이기 때문에 사례를 정리해봤습니다.

  1. thread 가 동일한 뮤텍스를 여러 번 재귀적으로 lock 을 필요로 할 때
  2. 여러 함수에서 같은 자원에 접근을 필요로 할 때

예제 코드를 2가지 준비했습니다.

(3) c++ recursive_mutex 활용

1. 예제 코드 – BinarySearchTree

#include <iostream>
#include <mutex>
#include <thread>
class BinarySearchTree{
public:
    BinarySearchTree(int value) : value(value) {}
    
    void insert(int newValue) {
        this->rec_mutex.lock();
        if (newValue < value) {
            if (left) {
                left->insert(newValue);
            } else {
                left = new BinarySearchTree(newValue);
            }
        } else if (newValue > value) {
            if (right) {
                right->insert(newValue);
            } else {
                right = new BinarySearchTree(newValue);
            }
        }
        this->rec_mutex.unlock();
    }
private:
    int value;
    BinarySearchTree* left = nullptr;
    BinarySearchTree* right = nullptr;
    std::recursive_mutex rec_mutex;
};
int main() {
    BinarySearchTree shared_root(50);
    std::thread node1([&shared_root]() { root.insert(30); });
    std::thread node2([&shared_root]() { root.insert(70); });
...
    node1.join();
    t2.join();
}

2. 예제 코드 – Shared Resource

class SharedResource {
public:
    void modify() {
        this->rec_mutex.lock();
        value++;
        this->print();
        this->rec_mutex.unlock();
    }
    void print() const {
        this->rec_mutex.lock();
        std::cout << value << std::endl;
        this->rec_mutex.unlock();
    }
private:
    mutable std::recursive_mutex rec_mutex;
    int value = 0;
};
int main() {
    SharedResource shared_resource;
    std::thread modify([&shared_resource]() { shared_resource.modify(); });
    std::thread print([&shared_resource]() { shared_resource.print(); });
...
    modify.join();
    print.join();
...
}

(4) 결론

c++ std::recursive_mutex 는 사용하면서 주의해야 할 게 하나 있습니다.
앞서 언급드렸던 바로 lock 과 unlock 의 횟수인데요,
이점 유의하시면서 안전한 코드 작성하셨으면 좋겠습니다.

c++ recursive_mutex 활용하기
태그:                 

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다