cpp11实现线程池(一)——项目介绍

news/2025/2/9 13:11:58/

项目介绍

线程池是库的形式提供给用户,是必须放到代码中,不能单独运行,亦称为基础组件

第一版线程池任务对象使用继承技术,提供一个抽象基类Task,里面有一个纯虚函数run(),使用时继承该类,并重写该纯虚函数,在这个重写的纯虚函数中完成要执行的具体任务;

第二版线程池使用C++11 的std::packaged_task<T>来包装任务执行函数,用std::future<T>来接受任意类型的结果

完整源代码

https://github.com/StrikeCode/cpp11_threadpool.git

技术点

熟练基于C++ 11标准的面向对象编程

组合和继承、继承多态、STL容器、智能指针、函数对象、绑定器、可变参模板编程等。

熟悉C++11多线程编程

threadmutexatomiccondition_variableunique_lock等。

C++17和C++20标准的内容

C++17的any类型和C++20的信号量semaphore,项目上都我们自己用代码实现。

熟悉多线程理论

多线程基本知识、线程互斥、线程同步、原子操作、CAS等。

线程池优点

服务进程启动之初,就实现创建好线程池,当业务流量到来时,需要线程就可以直接从线程池获取线程执行业务处理,不需要来一个任务创建一个线程,执行完任务再销毁线程,减少了线程的创建与销毁的开销

fixed线程池模式

线程池里面的线程个数是固定不变的,一般是ThreadPool创建时根据当前机器的CPU核心数量进行指定。

cached模式线程池

线程池里面的线程个数是可动态增长的,根据任务的数量动态的增加线程的数量,但是会设置一个线程数量的阈值(线程过多的坏处上面已经讲过了),任务处理完成,如果动态增长的线程空闲了60s还没有处理其它任务,那么关闭线程,保持池中最初数量的线程即可

多线程优势

多线程程序就一定好吗?不一定,需要具体分析场景

IO密集型

无论是CPU单核或者CPU多核还是多CPU,都是适合多线程(因为IO多就会造成CPU空闲)

CPU密集型

CPU单核情况下,不适合多线程,因为多线程存在上下文切换的开销,不如单线程直接执行完成,因为CPU密集型场景也不怎么到等待状态

线程池的开销

为了完成任务,创建很多的线程可以吗?

  • 线程的创建和销毁都是非常"重"的操作, 需要创建相应的数据结构如PCB task_struct,需要描述地址空间相应的数据结构 vm_struct、vm_area_struct,需要创建相应的页目录和页表项;
  • 线程栈(线程执行函数会使用到)本身占用大量内存,32位机一般一个进程最多只能创建380个线程左右,因为:
  • 假设一个线程需要8M内存空间,一个进程的虚拟内存用户空间为3G,3G/8M = 384;
  • 线程的上下文切换要占用大量时间;
  • 大量线程同时唤醒会使系统经常出现锯齿状负载或者瞬间负载量很大导致宕机,比如同一时间很多IO操作的已经完成

线程同步

竞态条件

指设备或系统临界区代码段出现不恰当的执行时序,而得到不正确的结果

如果多线程环境下不存在竞态条件,则称为可重入(多线程)的代码段,反之称为不可重入的代码段

线程互斥

  • 互斥锁

  • atomic原子类型,一般利用CAS操作(无锁机制)实现,常见应用:无锁队列、链表、数组(使用活锁)

线程通信

条件变量 condition_variable

使用方法:mutex+condition_variable

waitsignal的交互状态关系:

在这里插入图片描述

问题:用notify_one还是notify_all? notify_one可能会死锁

  • 信号量 semaphore

可以用条件变量封装一个信号量

信号量可看作资源计数没有限制的互斥量:

mutex.lock() //锁的资源计数1 -》0critical sectionmutex.unlock()//锁的资源计数0 -》1

控制的精度不如条件变量

用于保证操作时序,而没有对资源的互斥访问

使用wait (-1)和 post(+1) 方法


http://www.ppmy.cn/news/74117.html

相关文章

LeetCode:25. K 个一组翻转链表

25. K 个一组翻转链表 1&#xff09;题目2&#xff09;思路3&#xff09;代码4&#xff09;结果 1&#xff09;题目 给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k 是一个正整数&#xff0c;它的值小于或等于链表的长度。…

std::thread使用

std::thread使用 join & detachjoinable() 函数代码演示主线程不做操作joindetach join & detach 定义区别&#xff1a; join 会阻塞&#xff0c;调用线程等待子线程执行完毕&#xff0c;然后再往下执行detach 分离&#xff0c;调用线程不再等待子线程结束&#xff0…

【牛客刷题专栏】0x30:JZ38 字符串的排列(C语言编程题)

前言 个人推荐在牛客网刷题(点击可以跳转)&#xff0c;它登陆后会保存刷题记录进度&#xff0c;重新登录时写过的题目代码不会丢失。个人刷题练习系列专栏&#xff1a;个人CSDN牛客刷题专栏。 题目来自&#xff1a;牛客/题库 / 在线编程 / 剑指offer&#xff1a; 目录 前言问…

管中窥豹!从冠德石油看数字化对加油站的影响力

从上个世纪90年代起&#xff0c;至2010年前后&#xff0c;是国内信息化建设的高速发展期。这段时间无论是应用软件、企业网站还是商业咨询&#xff0c;无不呈现井喷式发展。大多数企业和政府机关均完成了或多或少的信息化建设。IT带来了标准化、科学化的管理和运作模式&#xf…

当Python遇上异步编程:实现高效、快速的程序运行!

前言 同步/异步的概念&#xff1a; 同步是指完成事务的逻辑&#xff0c;先执行第一个事务&#xff0c;如果阻塞了&#xff0c;会一直等待&#xff0c;直到这个事务完成&#xff0c;再执行第二个事务&#xff0c;顺序执行 异步是和同步相对的&#xff0c;异步是指在处理调用这…

C++——内存管理+模块

作者&#xff1a;几冬雪来 时间&#xff1a;2023年5月19日 内容&#xff1a;C——内存管理模块 目录 前言&#xff1a; 1.new和delete操作自定义类型&#xff1a; operator new/delete&#xff1a; 定位new表达式&#xff08;placement-new&#xff09;&#xff1a; …

Lucene(4):Field域类型

1 Field属性 Field是文档中的域&#xff0c;包括Field名和Field值两部分&#xff0c;一个文档可以包括多个Field&#xff0c;Document只是Field的一个承载体&#xff0c;Field值即为要索引的内容&#xff0c;也是要搜索的内容。 是否分词(tokenized) 是&#xff1a;作分词处理…

Git的项目管理工具的使用

Git的项目管理工具的使用 为什么学习Git软件&#xff1f; 主流开发中&#xff0c;基于互联网的开发项目都会使用git进行资源管理 资源管理&#xff1a;人力资源 ​ 代码资源 : .java .c . js 等 ​ 文档资源 &#xff1a; doc.md ,pdf 等 git是最常用的scm软件&#xff08;Soft…