线程 池(Linux高性能服务器编程)
发布时间:2022-12-12 13:02:39 所属栏目:Linux 来源:
导读: Linux高性能服务器编程 —— 游双 (复习笔记)
线程池定义
线程池是由服务器预先创建的一组子线程,线程池中的线程数量应该和 CPU 数量差不多。线程池中的所有子线程都运行着相同的代
线程池定义
线程池是由服务器预先创建的一组子线程,线程池中的线程数量应该和 CPU 数量差不多。线程池中的所有子线程都运行着相同的代
|
Linux高性能服务器编程 —— 游双 (复习笔记) 线程池定义 线程池是由服务器预先创建的一组子线程,线程池中的线程数量应该和 CPU 数量差不多。线程池中的所有子线程都运行着相同的代码。当有新的任务到来时,主线程将通过某种方式选择线程池中的某一个子线程来为之服务。 主线程选择子线程服务的方式: 主线程和所有子线程通过一个共享的工作队列来同步,子线程都睡眠在该工作队列上。当有新的任务到来时,主线程将任务添加到工作队列中。这将唤醒正在等待任务的子线程,不过只有一个子线程将获得新任务的”接管权“,它可以从工作队列中取出任务并执行之,而其他子线程将继续睡眠在工作队列上。 在这里插入图片描述 线程池如何实现? 1. 主线程轮流选取子线程 2. 通过共享队列+互斥量来同步 3. 信号量来通信 4. 同步问题 线程池的特点空间换时间,浪费服务器的硬件资源,换取运行效率。池是一组资源的集合,这组资源在服务器启动之初就被完全创建好并初始化,这称为静态资源。当服务器进入正式运行阶段,开始处理客户请求的时候,如果它需要相关的资源,可以直接从池中获取,无需动态分配。当服务器处理完一个客户连接后,可以把相关的资源放回池中,无需执行系统调用释放资源。线程数量(取决于CPU数量)CPU密集型,线程数和CPU数目相同即可I/O密集型,线程数目可以大一点。 (线程等待时间/线程CPU时间 + 1)* CPU数目具体实现 #ifndef THREADPOOL_H #define THREADPOOL_H #include #include #include #include #include class ThreadPool { public: explicit ThreadPool(size_t threadCount = 8): pool_(std::make_shared<Pool>()) { assert(threadCount > 0); for(size_t i = 0; i < threadCount; i++) { std::thread([pool = pool_] { std::unique_lock<std::mutex> locker(pool->mtx); while(true) { if(!pool->tasks.empty()) { auto task = std::move(pool->tasks.front()); pool->tasks.pop(); locker.unlock(); task(); locker.lock(); } else if(pool->isClosed) break; else pool->cond.wait(locker); } }).detach(); //线程分离 } } ThreadPool() = default; ThreadPool(ThreadPool&&) = default; ~ThreadPool() { if(static_cast<bool>(pool_)) { { std::lock_guard<std::mutex> locker(pool_->mtx); pool_->isClosed = true; } pool_->cond.notify_all(); } } template<class F> void AddTask(F&& task) { { std::lock_guard<std::mutex> locker(pool_->mtx); pool_->tasks.emplace(std::forward<F>(task)); } pool_->cond.notify_one(); } private: struct Pool { std::mutex mtx; //互斥锁 std::condition_variable cond; //条件变量 bool isClosed; //是否关闭 std::queue<std::function<void()>> tasks; //工作队列 }; std::shared_ptr<Pool> pool_; }; #endif //THREADPOOL_H notify_one()与notify_all() 两者用来唤醒阻塞的线程,线程被唤醒后立即尝试获得锁。 notify_one()因为只唤醒一个线程,不存在锁争用,所以能够立即获得锁。其余的线程不会被唤醒,需要等待再次调用notify_one()或者notify_all()。 notify_all()会唤醒所有阻塞的线程,存在锁争用,只有一个线程能够获得锁。那其余未获取锁的线程继续尝试获得锁(类似于轮询)线程池linux,而不会再次阻塞。当持有锁的线程释放锁时,这些线程中的一个会获得锁。而其余的会接着尝试获得锁。 (编辑:财气旺网 - 财气网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
站长推荐

