前言
在阅读 c++ 实现的 WebServer 源码时,感觉其中线程池实现值得具体分析,此篇博客分析该源码中线程池实现部分。
源码
|
|
源码分析
为什么该线程池所有的实现在 threadpool.h 中完成?
上面源码为线程池的头文件
threadpool.h,而且该线程池没有对应的threadpool.cpp实现代码文件,这种在类中实现方法的方式,使得类中方法都是缺省内联的,这样在编译的时候把函数调用的部分直接换成函数代码,而不是进行函数调用,这适用于函数代码少的时候,可以避免调用带来栈空间的消耗,也可以减少一定的调用时间。
explicit 修饰的构造函数如何理解?
通过将构造函数声明为explicit(显式)的方式可以抑制隐式转换。也就是说,explicit构造函数必须显式调用。按默认规定,只用传一个参数的构造函数也定义了一个隐式转换。具体参考:C++ explicit关键字详解
std::make_shared 作用是什么?在什么场景下使用?
如有可能,第一次创建内存资源时,请使用
make_shared函数创建shared_ptr。make_shared异常安全。 它使用同一调用为控制块和资源分配内存,这会减少构造开销。 如果不使用make_shared,则必须先使用显式new表达式来创建对象,然后才能将其传递到shared_ptr构造函数。具体参考:如何:创建和使用 shared_ptr 实例
void detach() 作用?
拆离相关联的线程。 操作系统负责释放终止的线程资源。具体参考:thread类-detach
std::unique_lock 作用及应用场景?
表示可进行实例化以创建管理
mutex锁定和解锁的对象的模板。uniqie_lock是个类模板,它的功能跟lock_quard类似,但比lock_quard更灵活。在工作中,一般用lock_quard(推荐使用)就足够了,但在一些特殊的场景下会用到uniqie_lock。lock_quard取代了mutex的lock()和unlock(),在lock_quard的构造函数中上锁,在析构函数中解锁,这点其实在uniqie_lock中也是一样的。uniqie_lock在使用上比lock_quard灵活,但代价就是效率会低一点,并且内存占用量也会相对高一些。具体参考:unique_lock详解 和 unique_lock 类
std::mutex 作用及应用场景?
Mutex又称互斥量,C++ 11中与Mutex相关的类(包括锁类型)和函数都声明在<mutex>头文件中,所以如果你需要使用std::mutex,就必须包含<mutex>头文件。std::mutex是C++11 中最基本的互斥量,std::mutex对象提供了独占所有权的特性——即不支持递归地对std::mutex对象上锁,而std::recursive_lock则可以递归地对互斥量对象上锁。具体参考:C++11 并发指南三(std::mutex 详解)
std::move 与 std::forward 作用及应用场景?
std::forward比std::move逻辑略复杂,std::move是无条件把参数转换为右值,而std::forward在特定情况下才会这样做:仅当参数是用右值初始化时,才会把它转换为右值。它的意义是使外面的函数调用选择接受右值的版本,实际的移动工作是由外面的函数进行的;使用std::forward来转发参数一般被称为完美转发 (也叫精确传递)。具体参考:C++ 理解std::forward完美转发。这里,使用std::move将pool->tasks.front()装换为右值,从而使得std::function类型的task调用function& operator= (function&& rhs);构造函数,避免资源重复申请创建。详细讨论参考:知乎std::move回答