C++多线程应用
一个进程就是一个程序,一个程序里不止一个功能,每个功能的实现就可以交给一个线程去完成。一个进程就像是一个工程,这个工程里,有设计,有监理,有施工,就相当于三个线程,各干各的又相互配合。
https://cplusplus.com/reference/thread/thread/thread/
是C++的官方参考,个人觉得比较权威,比经过一些人去了解更好。每个人的思维方式不一样,直接看原始文档是最好的,何必吃别人嚼过的饭呢。
下面是我的心得,也算个参考吧。
一、创建一个线程大致有两种方法,一是先定义一个空线程,然后再实例化,二是直接实例化一个线程,直接干活。我个人倾向第二种,感觉第一种没什么意义。
二、对于join的理解。我的理解是:一个线程就是一个人,给这个人派任务后,有两种状态,一个是需要他回复,另一种是不需要。需要回复的,就用join,不需要回复的,就用detach。还拿设计,监理,施工,三人举例。施工前需要设计好才能开始施工,设计线程需要join,施工和监理是同时进行的,不能等施工完了,监理才检查,所以施工尤其不能join,只能detach,监理就可以马上开始了,监理作为最后一个工序可以join,也可以detach
三、joinable,就是表示这个线程的状态,一个线程,既有任务,又需要回复,就是joinable()== true,其余状态都是joinable()== false
四、当joinable()== true时,才对线程进行join或detach操作。否则不要进行这两种操作。即if(th.joinable()){th.join();或th.detach();}
五、std::hardware_concurrency()是CPU的核心数,按理说是一个核心对应一个线程。但是一个线程在执行完任务后就自动销毁了,CPU核心就空出来了。让线程等待新任务的话,也行,但我在实际运行过程中,会报错,也许是我学艺不精。我就简单粗暴,不断创建新线程。
六、线程池的概念我也不知道是谁发明的,就是先创建几个空线程,没事就等着,有事就干,干完也不消毁,继续等,说是能节约时间,我是觉得没什么用,而且官方参考里并没有这个说法。
上代码,用注释说明。
//此程序用多线程去调查学生的情况并记录。
#include <atomic> // 自锁型变量,防止多线程交叉操作,只能一个一个来,本例子并未使用,好像不支持string。
#include <thread> // 想用多线程,就要包含此包
#include <vector> // 使用多线程的辅助工具,任意类型的队列
#include <mutex> // 防止线程交叉操作同一代码用的,线程锁
mutex m; //定义一个线程锁
string a=“”; //用于记录的字符串
std::vector<std::thread> threaders;//创建一个线程队列,没有上限
//次子程序,用于获取学生的属性并记录,参数是学号,用很多线程执行这个子程序,一个线程调查一个学生,调查完不需要回复。这里假设,获取属性是个费时的工作,记录是个很快的动作,四个get_XXX()是预先写好的其他子程序。
void get_students_status(int student_number) //学号是学生的唯一标识
{
string name; //学生的姓名
string age; //学生的年龄
string height; //学生的身高
string weight; //学生的体重
name = get_name(student_number);
age = get_age(student_number);
height = get_height(student_number);
weight = get_weight(student_number);
//前面是调查的工作,可以多线程同步进行。后面是记录的工作,不能多线程同步进行,必须一个一个来,就需要加锁。这会让程序整体变慢,但没办法,记录是配套的,否则就乱了,比如名字后面应该是年龄,如果不加锁,可能会是另一个人的名字,
m.lock(); //加锁
a = a + name+": "+age +" "+height+" "+weight +"||";
m.unlock(); //解锁
}
main()
{
//对一万个学生进行调查并记录
for(int i = 1;i<10000;i++)
{
threaders.push_back(std::thread(get_students_status,i)); //针对每个学号创建一个线程,std::thread是创建线程的语句,其第一个参数是线程执行的子程序,第二个参数是该子程序的第一个参数,以此类推。threaders.push_back是把这个新创建的线程放在线程队列的队尾。
//遍历线程队列里的每个线程
for (auto& th : threaders)
{
if(th.joinable())th.detach();//如果此线程处于有任务,且需要回复的状态,就告诉他不用回复了。此处用join,就是等待其回复。那样就失去了多线程的意义,一个一个干,跟一个人干,没什么区别。
}
}
m.lock(); //加锁
cout<<a<<endl;//有可能还有线程没完成就输出了,可以想别的办法,比如前面加sleep(),或加锁。主线程也是线程啊。也可以在前面遍历线程那步,把最后一个线程join
m.unlock(); //解锁
}
C++多线程应用的更多相关文章
- Python中的多进程与多线程(一)
一.背景 最近在Azkaban的测试工作中,需要在测试环境下模拟线上的调度场景进行稳定性测试.故而重操python旧业,通过python编写脚本来构造类似线上的调度场景.在脚本编写过程中,碰到这样一个 ...
- 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例
前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...
- 多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类)
前言:刚学习了一段机器学习,最近需要重构一个java项目,又赶过来看java.大多是线程代码,没办法,那时候总觉得多线程是个很难的部分很少用到,所以一直没下决定去啃,那些年留下的坑,总是得自己跳进去填 ...
- Java多线程
一:进程与线程 概述:几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是一个线程. 进程:进程 ...
- .NET基础拾遗(5)多线程开发基础
Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...
- Java多线程基础——对象及变量并发访问
在开发多线程程序时,如果每个多线程处理的事情都不一样,每个线程都互不相关,这样开发的过程就非常轻松.但是很多时候,多线程程序是需要同时访问同一个对象,或者变量的.这样,一个对象同时被多个线程访问,会出 ...
- C#多线程之线程池篇3
在上一篇C#多线程之线程池篇2中,我们主要学习了线程池和并行度以及如何实现取消选项的相关知识.在这一篇中,我们主要学习如何使用等待句柄和超时.使用计时器和使用BackgroundWorker组件的相关 ...
- C#多线程之线程池篇2
在上一篇C#多线程之线程池篇1中,我们主要学习了如何在线程池中调用委托以及如何在线程池中执行异步操作,在这篇中,我们将学习线程池和并行度.实现取消选项的相关知识. 三.线程池和并行度 在这一小节中,我 ...
- C#多线程之线程池篇1
在C#多线程之线程池篇中,我们将学习多线程访问共享资源的一些通用的技术,我们将学习到以下知识点: 在线程池中调用委托 在线程池中执行异步操作 线程池和并行度 实现取消选项 使用等待句柄和超时 使用计时 ...
- C#多线程之线程同步篇3
在上一篇C#多线程之线程同步篇2中,我们主要学习了AutoResetEvent构造.ManualResetEventSlim构造和CountdownEvent构造,在这一篇中,我们将学习Barrier ...
随机推荐
- AI 大模型时代呼唤新一代基础设施,DataOps 2.0和调度编排愈发重要
在 AI 时代,DataOps 2.0 代表了一种全新的数据管理和操作模式,通过自动化数据管道.实时数据处理和跨团队协作,DataOps 2.0 能够加速数据分析和决策过程.它融合了人工智能和机器学习 ...
- DolphinScheduler分布式集群部署指南(小白版)
官方文档地址:https://dolphinscheduler.apache.org/zh-cn/docs/3.1.9 DolphinScheduler简介 摘自官网:Apache DolphinSc ...
- React的prop-types下载安装教程
最近刚入门react,所有react的资源都是从本地导入的,这就难免要去网上找要用的包,react包和reactdom,还有babel的包都挺好找的,官网就有现成的可以用,但是prop-types包貌 ...
- 【Homebrew】之相关命令问题合集及iOS真机调试包
一.Homebrew更换国内镜像源(中科大.阿里.清华) Homebrew主要有四个部分组成: brew.homebrew-core .homebrew-bottles.homebrew-cask. ...
- 从Workload中优雅隔离Pod
线上集群中,业务跑着跑着,突然发现有个Pod上出现大量错误日志,其他的Pod是正常的,该如何处理呢? 直接删除Pod? 这样不便于保留现场,可能会影响判断问题的根因 让业务方忍一会,先排查下问题? 会 ...
- C语言输出格式工整的日历——2乘6样式(详见本文)
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码如不能在Dev-C++上完好运行,出现如下问题: E:\Dev-Cpp\源代码\万年历.c [Error] 'for' loop initia ...
- echarts 等相关问题解答过程
echarts 绘制中国地图https://blog.csdn.net/sleepwalker_1992/article/details/126959198 elmentui table数据轮播显示: ...
- Nuxt Kit 中的上下文处理
title: Nuxt Kit 中的上下文处理 date: 2024/9/16 updated: 2024/9/16 author: cmdragon excerpt: Nuxt Kit 提供的上下文 ...
- 暑假集训SCP提高模拟10
我(看着百度百科):我已经知道这场谁组的题了 CTH: 谁 我:你想想,能在模拟赛里塞四道数学题还玩邦的,还能有谁 CTH: 我不知道 我:我不知道 CTH: 我知道了 我:我知道了 我:我是 Bob ...
- Kubernetes Pod生命周期(十七)
前面我们已经了解了 Pod 的设计原理,接下来我们来了解下 Pod 的生命周期.下图展示了一个 Pod 的完整生命周期过程,其中包含 Init Container.Pod Hook.健康检查 三个主要 ...