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 ...
随机推荐
- 【VMware ESXi】把硬盘当内存用?VMware 内存分层(Memory Tiering),你值得拥有!
VMware vSphere 8.0 U3 发布了一个非常有意义的功能叫内存分层(Memory Tiering),以利用基于 PCIe 的 NVMe 设备充当第二层(辅助)内存,从而使 ESXi 主机 ...
- QT的基础设置(菜单栏、状态栏、任务栏。。。。)
Qt [1] 是一个1991年由Qt Company开发的跨平台C++图形用户界面应用程序开发框架.它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器.下面介绍QT的基础配置 1 ...
- 19-canvas绘制文字
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="U ...
- [CSP-S 2023] 消消乐 & CF1223F 题解
LG9753 CF1223F 我们称一个字符串是可消除的,当且仅当可以对这个字符串进行若干次操作,使之成为一个空字符串.其中每次操作可以从字符串中删除两个相邻的相同字符,操作后剩余字符串会拼接在一起. ...
- Buckingham-Reiner 方程和 Darby-Melson 经验方程
由 Roni, et al. (2018), Woolley, et al. (2014), Yang, et al. (2017) 整理人便便的物理性质数据如下: 性质 值 密度 \((\text{ ...
- .NET中各种线程同步锁
编程编的久了,总会遇到多线程的情况,有些时候我们要几个线程合作完成某些功能,这时候可以定义一个全局对象,各个线程根据这个对象的状态来协同工作,这就是基本的线程同步. 支持多线程编程的语言一般都内置了 ...
- Linux离线安装Tomcat
系统环境: centos7.3.1611 openjdk version "1.8.0_102" apache-tomcat-9.0.36.tar.gz tomcat 安装 #链接 ...
- 细说WebService
细说WebService 简介 WebService 是一个应用于客户端.服务端,基于http协议的web应用程序,他有一个非常重要的特点,那就是可以跨语言.跨平台进行远程调用,可应用于分布式系统中的 ...
- 记一次list集合优化
已知某个列表List1有2000条数据,但是因为这个列表的某个字段要从另一个表查询,所以根据一个关联的查询条件查出来的另一个List2有将近75000条数据,然后需要先循环第一个List1,然后循环里 ...
- React挂载dom无效的问题
话不多说,先上代码. 根据我的猜测,ReactDOM.render()这个函数,也就是挂载的意思是将内容进行替换,所以我的vdom1在调试的时候没有展示出来. 然后我创建了两个div块,分别挂载vdo ...