C++ 多线程笔记1 线程的创建
C++ 多线程笔记1 线程的创建
里面代码会用到的头文件
#include <iostream>
#include <string>
#include <memory>
#include <thread>
#include <vector>
#include <stdlib.h>
#include <cmath>
#include <chrono>
#include <ctime>
入门例子
void mytest()
{
std::cout<<"hello"<<'\n';
}
int main()
{
std::thread t(mytest); //开启一个线程
std::cout<<"hello world\n";
t.join(); //终结线程
}
/*输出
hello world
hello
*/
1.上面的代码使用了
std::thread t
,这行代码创建了一个新的线程t
,并让它执行mytest函数。当这行代码执行时,mytest函数会在新创建的线程
上开始执行。主线程(即创建t的线程)
则会继续执行下一行代码。2.
t.join()是一个阻塞调用
,意味着主线程会等待,直到线程t(即mytest函数)执行完毕。换句话说,t.join()
确保了mytest函数在新线程上完成执行后,主线程才会继续执行后续的代码。如果没有t.join()
,主线程可能在mytest函数完成之前结束,这可能会导致未定义的行为,因为当主线程结束时,所有其他线程都会被强制终止,即使它们还没有完成它们的任务。
利用多线程去计算
多线程可以加快数组元素的计算,例如,我们先创建一个数组,来进行普通的计算,顺便测试一下运行速度。
//一个简单计算的例子
double cf(double v)
{
if (v<=0)
return v;
std::this_thread::sleep_for(std::chrono::milliseconds(1));//让线程停下来1毫秒
return sqrt((v * v+std::sqrt((v-5)*(v+2.5) )/2.0 )/v); //随便的计算
}
std::vector<double> vds;
for(int i=0;i<1000;++i)
vds.push_back(rand()); //随机赋值
std::cout<<vds.size()<<'\n'; //大小
double value=0.0;
auto nowc = clock();//现在的时间
for(auto& info :vds)
{
value += cf(info);
}
std::cout<<"value: "<<value<<"spend time is "<<clock()-nowc<<'\n';
输出内容
1000
value: 120539spend time is 16760
接下来,我们使用多线程来计算一下数组元素,我们让主线程计算一半数组元素,开一个线程计算另外一半数组元素。
在多线程中
//这个函数是给数组中从Begin位置到End位置中元素进行计算
template<class T,typename Fun>
double visit(std::thread::id id,T iterBegin,T iterEnd,Fun f)
{
auto mainThreadId = std::this_thread::get_id();//获取主线程id
if(id == mainThreadId)
std::cout<<"This is MAIN Thread \n";
else
std::cout<<"This is WORK Thread \n";
double v=0;
for(auto iter=iterBegin; iter!=iterEnd;++iter)
v+=f(*iter);
return v;
}
auto iter = vds.begin() +(vds.size()/2);//数组的后一半
double anotherv = 0.0;
auto iterEnd = vds.end();
nowc = clock();
std::thread s( //这里的mainThreadId
[&anotherv,iter,iterEnd,mainThreadId]()
{
anotherv=visit(mainThreadId,iter,iterEnd,cf);//将当前线程id,计算数组后半的数据
});
auto halfv = visit(mainThreadId,vds.begin(),iter,cf); //计算数组前半的数据
s.join();
std::cout<<"halfv+anotherv: "<<(halfv+anotherv)<<"spend time is "<<clock()-nowc<<'\n';
输出内容
This is MAIN Thread
This is WORK Thread
halfv+anotherv: 120539spend time is 7890
由此可见,用多线程的技术后,计算速度比普通计算快接近一半.我们还可以建立三线程等更多线程来计算
//三线程代码
auto mainThreadId = std::this_thread::get_id();//获取主线程id
std::vector<double> vds;
for(int i=0;i<300;++i)
vds.push_back(rand());
std::cout<<vds.size()<<'\n';
double value=0.0;
// 让我们测试一下运行速度
auto nowc = clock();//现在的时间
for(auto& info :vds)
{
value += cf(info);
}
std::cout<<"value: "<<value<<" spend time is "<<clock()-nowc<<'\n';
auto begin1 = vds.begin();
auto iter = vds.begin() +(vds.size()/3);
auto iter2 = iter+(vds.size()/3);
double anotherv = 0.0;
double anotherv2 = 0.0;
auto iterEnd = vds.end();
nowc = clock();
std::thread s( //这里的mainThreadId
[&anotherv,begin1,iter,mainThreadId]()
{
anotherv=visit(mainThreadId,begin1,iter,cf);//将当前线程id,计算数组后半的数据
});
std::thread s2( //这里的mainThreadId
[&anotherv2,iter,iter2,mainThreadId]()
{
anotherv2=visit(mainThreadId,iter,iter2,cf);//将当前线程id,计算数组后半的数据
});
auto halfv = visit(mainThreadId,iter2,vds.end(),cf); //计算数组前半的数据
s.join();
s2.join();
std::cout<<"halfv+anotherv: "<<(halfv+anotherv+anotherv2)<<" spend time is "<<clock()-nowc<<'\n';
/*
输出
300
value: 36321.9 spend time is 4734
This is MAIN Thread
This is WORK Thread
This is WORK Thread
halfv+anotherv: 36321.9 spend time is 1582
*/
关于线程中的 mainThreadId
还有几点,有以下几点需要澄清:
线程 ID 的唯一性
:1std::this_thread::get_id() 1返回调用线程的唯一标识符。因此,主线程和任何新创建的线程都会有不同的 ID。即使您在主线程中和新线程中都调用了 std::this_thread::get_id() 并将其赋值给 mainThreadId,这两个变量也会持有不同的值,因为它们是不同线程的 ID。捕获列表的作用
:在 s 线程的捕获列表中,1mainThreadId 是通过引用捕获的1。这意味着 s 线程中的 mainThreadId 是 main 函数中 mainThreadId 的一个引用。但是,这并不意味着 s 线程中的 mainThreadId 就是主线程的 ID。它只是 main 函数中定义的同一个变量的引用。变量的生命周期
:只要 main 函数还在执行,并且 mainThreadId 还在其作用域内,s 线程就可以通过其捕获的引用访问 mainThreadId。但是,一旦 main 函数结束,mainThreadId 的生命周期也就结束了,此时对 s 线程中捕获的引用的访问将是未定义的。
C++ 多线程笔记1 线程的创建的更多相关文章
- Java多线程并发01——线程的创建与终止,你会几种方式
本文开始将开始介绍 Java 多线程与并发相关的知识,多谢各位一直以来的关注与支持.关注我的公众号「Java面典」了解更多 Java 相关知识点. 线程的创建方式 在 Java 中,用户常用的主动创建 ...
- AJ学IOS(49)多线程网络之线程的创建NSThreand
AJ分享,必须精品 一:NSThread的基本使用 1:创建和启动线程 一个NSThread对象就代表一条线程 创建.启动线程 NSThread *thread = [[NSThread alloc] ...
- 【Java】多线程相关复习—— 线程的创建、名字、运行情况以及顺序控制(join方法) 【一】
一.创建线程的三种方式 · 继承Thread类 · 实现Runnable接口 · 实现Callable接口 二. 线程状态 · 线程名字 getName() · 线程活动情况 isAlive() · ...
- JAVA学习笔记16——线程的创建和启动
Java使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例.每个线程的作用是完成一定的任务,实际上就是执行一段程序流(一段顺序执行的代码).Java使用线程执行体来代表这段 ...
- linux多进/线程编程(7)——多线程1(线程的创建,回收,分离,设置线程属性等)
参考资料: 1.博客1:https://blog.csdn.net/zhou1021jian/article/details/71531699 2.博客2:https://blog.csdn.net/ ...
- Java多线程并发02——线程的生命周期与常用方法,你都掌握了吗
在上一章,为大家介绍了线程的一些基础知识,线程的创建与终止.本期将为各位带来线程的生命周期与常用方法.关注我的公众号「Java面典」了解更多 Java 相关知识点. 线程生命周期 一个线程不是被创建了 ...
- iOS-多线程 ,整理集锦,多种线程的创建
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launc ...
- java笔记--使用线程池优化多线程编程
使用线程池优化多线程编程 认识线程池 在Java中,所有的对象都是需要通过new操作符来创建的,如果创建大量短生命周期的对象,将会使得整个程序的性能非常的低下.这种时候就需要用到了池的技术,比如数据库 ...
- Linux多线程编程——线程的创建与退出
POSIX线程标准:该标准定义了创建和操纵线程的一整套API.在类Unix操作系统(Unix.Linux.Mac OS X等)中,都使用Pthreads作为操作系统的线程.Windows操作系统也有其 ...
- Java多线程之线程的创建
好久没有更博客了,最近一直在忙工作的事情.现在终于空下来了,这2天会抓紧时间整理多线程和socket,把JavaSE结束掉. 关于多线程,首先会涉及到哪些东西呢?首先要了解线程,为什么要使用线程,线程 ...
随机推荐
- rel分支合并进入dev分支有冲突怎么处理?
rel分支合并进入dev分支有冲突怎么处理? 切换到本地rel 拉取远端rel 切换本地dev 拉去远端dev git merge rel 会出现冲突 解决后 推送到远端就可以
- echarts更改x和y轴的颜色
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- 【学到了】golang的[]byte可以append string类型的数据
上代码: func Test_use_string(t *testing.T){ arr := make([]byte,0, 100) arr = append(arr, "abcd&quo ...
- C/C++ Qt 命令行版网络通信
通常情况下Qt如果需要建立网络通信则必须依附于图形界面,但如果是新手入门,图形界面则显得太过于繁琐不利于学习原理,如下本人实现了命令行版本的网络通信案例,能够让读者更好的理解Qt是如何创建网络通信套接 ...
- Redis主从配置、数据持久化、集群
发布订阅 ## subscribe 订阅一个或者多个频道 ## publish 给指定的频道发送消息 ## psubscribe 订阅指定模式的频道,*代表所有 ## pubsub channels ...
- powerDesigner 逆向工程 mysql 生成 PDM
1. 信息补充说明 powerDesigner 16.5 mysql 5.6 主要内容:使用powerDesigner的逆向工程,将mysql中的数据库转换成PDM文件 所需资源: powerDe ...
- Intel 14代酷睿提前上架加拿大:涨价最多7%
Intel将在10月17日正式发布14代酷睿,说白了就是13代酷睿升级版,代号就能说明一切--Raptor Lake Refresh. 首批发布的只是高端的K/KF系列,一共六款,分别是8+16 24 ...
- Google_Book_20Things.前言以及前四项学习笔记
20 THINGS I LEARNED ABOUT BROWSERS AND THE WEB Illustrated by Christoph Niemann. Written by the Goog ...
- idea破解《当脚本破解方式无效或不方便执行时可采用此方法》
idea新版破解有时会各种不成功,很耽误事.所以,再次整理一个相对省事有效的办法.<此方式为修改idea启动脚本破解方式>内容如下: 一:下载此激活工具 二:按下图从下载的文件中找到箭头标 ...
- PyTorch下,使用list放置模块,导致计算设备不一的报错
报错 在复现 Transformer 代码的训练阶段时,发生报错: RuntimeError: Expected all tensors to be on the same device, but f ...