[c++] 스레드 풀과 데드락 방지

이번에는 C++에서 스레드 풀을 사용하고 데드락을 방지하는 방법에 대해 알아보겠습니다.

스레드 풀이란?

스레드 풀은 일반적으로 스레드를 미리 생성하여 관리하는 기술입니다. 이를 통해 스레드 생성 및 제거에 따른 오버헤드를 줄일 수 있으며, 재사용 가능한 스레드를 유지하여 작업을 효율적으로 처리할 수 있습니다.

아래는 C++11에서 제공하는 스레드 풀의 간단한 예제입니다.

#include <iostream>
#include <vector>
#include <thread>
#include <mutex>

class ThreadPool {
public:
    ThreadPool(size_t num_threads) : stop(false) {
        for (size_t i = 0; i < num_threads; ++i) {
            workers.emplace_back([this] {
                while (true) {
                    std::function<void()> task;
                    {
                        std::unique_lock<std::mutex> lock(queue_mutex);
                        condition.wait(lock, [this] { return stop || !tasks.empty(); });
                        if (stop && tasks.empty()) {
                            return;
                        }
                        task = std::move(tasks.front());
                        tasks.pop();
                    }
                    task();
                }
            });
        }
    }

    template<class F>
    void enqueue(F&& f) {
        {
            std::unique_lock<std::mutex> lock(queue_mutex);
            tasks.emplace(std::forward<F>(f));
        }
        condition.notify_one();
    }

    ~ThreadPool() {
        {
            std::unique_lock<std::mutex> lock(queue_mutex);
            stop = true;
        }
        condition.notify_all();
        for (std::thread &worker : workers) {
            worker.join();
        }
    }

private:
    std::vector<std::thread> workers;
    std::queue<std::function<void()>> tasks;
    std::mutex queue_mutex;
    std::condition_variable condition;
    bool stop;
};

데드락 방지

데드락은 둘 이상의 프로세스나 스레드가 서로 상호 배제적인 자원을 점유하며, 상대방이 점유한 자원을 요청하면서 무한 대기 상태에 빠지는 문제입니다.

C++에서 데드락을 방지하는 방법으로는 RAII(Resouce Acquisition Is Initialization) 기법을 사용하는 것이 효과적입니다. RAII를 사용하면 자원 획득과 해제를 객체의 생성과 소멸과 맞추어 처리할 수 있으므로 데드락이 발생할 확률을 줄일 수 있습니다.

또한, C++11부터는 std::lock을 사용하여 여러 개의 뮤텍스를 안전하게 잠글 수 있는 기능을 제공하므로, 이를 활용하여 데드락을 방지할 수 있습니다.

결론

C++에서 스레드 풀을 사용하여 비동기 작업을 효율적으로 처리하고, RAII 및 std::lock을 활용하여 데드락을 방지할 수 있습니다.