[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
을 활용하여 데드락을 방지할 수 있습니다.