加入收藏 | 设为首页 | 会员中心 | 我要投稿 拼字网 - 核心网 (https://www.hexinwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

线程池(Linux高性能服务器编程)

发布时间:2022-10-26 14:31:32 所属栏目:Linux 来源:互联网
导读: Linux高性能服务器编程 —— 游双 (复习笔记)
线程池定义
线程池是由服务器预先创建的一组子线程,线程池中的线程数量应该和 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,而不会再次阻塞。当持有锁的线程释放锁时,这些线程中的一个会获得锁。而其余的会接着尝试获得锁。

(编辑:拼字网 - 核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!