写一个C++线程安全的线程池,并举例说明
时间: 2024-10-08 21:06:36 浏览: 47
线程池是一种常见的并发工具,它可以有效地管理多个线程,提高程序性能并避免频繁地创建和销毁线程所导致的开销。在C++中,我们可以使用`std::thread_pool`(如果它是STL的一部分,但标准库并没有提供这个接口)或自定义实现来创建线程池。
以下是一个简单的自定义线程池示例,使用`std::vector`存储线程,以及一个条件变量和互斥锁来确保线程安全:
```cpp
#include <vector>
#include <condition_variable>
#include <mutex>
#include <future>
class ThreadPool {
public:
ThreadPool(size_t thread_count) : stopped(false), threads(thread_count) {
for (size_t i = 0; i < thread_count; ++i) {
threads[i] = std::thread([this] { worker(); });
}
}
~ThreadPool() {
// 设置停止标志,然后等待所有任务完成
stop();
join_threads();
}
template<typename Func, typename... Args>
auto enqueue(Func&& func, Args&&... args) -> std::future<decltype(func(args...))> {
std::lock_guard<std::mutex> lock(queue_mutex);
tasks.emplace_back(std::move(func), std::forward<Args>(args)...);
condition.notify_one();
return task_results.front();
}
private:
void worker() {
while (!stopped) {
std::unique_lock<std::mutex> lock(queue_mutex);
condition.wait(lock, [this] { return !tasks.empty() || stopped; });
if (!tasks.empty()) {
std::packaged_task<decltype(tasks.back().first)> task = tasks.front();
tasks.pop_front();
try {
task.call_soon();
} catch (...) {
// Handle exceptions in the background
}
}
}
}
void stop() {
stopped = true;
condition.notify_all();
}
void join_threads() {
for (auto& t : threads) {
if (t.joinable()) {
t.join();
}
}
}
std::vector<std::thread> threads;
std::queue<std::packaged_task<decltype(tasks.back().first)>> tasks;
std::mutex queue_mutex;
std::condition_variable condition;
std::deque<std::future<decltype(tasks.back().first)>> task_results; // For returning results
};
// 示例用法
int main() {
ThreadPool pool(4);
for (int i = 0; i < 10; ++i) {
pool.enqueue([](int n) { std::cout << "Task " << n << " started by thread " << std::this_thread::get_id() << '\n'; }, i);
}
// 所有任务完成后,线程池自动关闭
return 0;
}
```
在这个例子中,我们创建了一个线程池,当有新的任务(`enqueue`方法中的函数)加入时,会在队列中等待处理。当一个线程空闲时,它会从队列中取出一个任务执行。
线程池的安全主要体现在对任务队列的访问上,通过`std::mutex`和`std::condition_variable`保证了多线程环境下的线程同步。
阅读全文