[c++] 스레드 풀과 작업 완료 후처리

스레드 풀은 작업을 처리하는 데 사용되는 스레드의 고정된 집합입니다. 스레드 풀을 사용하면 성능이 향상되고 자원이 효율적으로 활용됩니다. 이번 포스트에서는 C++ 스레드 풀을 사용하여 작업을 처리하고 완료 후처리를 하는 방법에 대해 알아보겠습니다.

1. 스레드 풀 생성

스레드 풀을 생성하기 위해선 C++11 이상을 지원하는 컴파일러가 필요합니다. std::thread 대신 std::thread_pool을 사용하고 싶다면 C++17 이상이 필요합니다.

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

class ThreadPool {
public:
    explicit ThreadPool(size_t numThreads) {
        for (size_t i = 0; i < numThreads; ++i) {
            threads.emplace_back([=] {
                while (true) {
                    std::function<void()> task;
                    {
                        std::unique_lock<std::mutex> lock(mutex);
                        condition.wait(lock, [=] { 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(mutex);
            tasks.emplace(std::forward<F>(f));
        }
        condition.notify_one();
    }

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

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

int main() {
    ThreadPool pool(4);
    // 작업을 스레드 풀에 추가하고 완료 후처리
    pool.enqueue([]{ /* 작업 내용 */ });
    pool.enqueue([]{ /* 작업 내용 */ });
    pool.enqueue([]{ /* 작업 내용 */ });
    // ...
    return 0;
}

2. 작업 완료 후처리

위 예제에서 ThreadPool 클래스의 enqueue 함수를 통해 작업을 스레드 풀에 추가하고, 해당 작업이 완료된 후에 후처리를 할 수 있습니다.

int main() {
    ThreadPool pool(4);
    pool.enqueue([]{
        // 작업 내용
        // ...
        // 작업 완료 후처리
        std::cout << "Task 1 completed" << std::endl;
    });
    pool.enqueue([]{
        // 작업 내용
        // ...
        // 작업 완료 후처리
        std::cout << "Task 2 completed" << std::endl;
    });
    pool.enqueue([]{
        // 작업 내용
        // ...
        // 작업 완료 후처리
        std::cout << "Task 3 completed" << std::endl;
    });
    // ...
    return 0;
}

결론

C++ 스레드 풀을 사용하여 작업을 처리하고 완료 후처리를 하는 방법에 대해 알아보았습니다. 스레드 풀은 멀티스레드 프로그래밍에서 성능과 효율성 향상을 위해 중요한 개념 중 하나입니다. 이를 통해 병렬 작업을 효과적으로 처리하고 프로그램의 성능을 개선할 수 있습니다.

본 포스트는 cppreference.com을 참고하여 작성되었습니다.