215-C++多线程(基本使用)

C11多线程

线程库

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

thread里面有什么函数?

在这里插入图片描述

上代码!(举例子)

在VS2019进行
为了支持线程库,我们需要设置,在项目的管理属性设置。

在这里插入图片描述
sleep函数
在这里插入图片描述
相当于全局函数,不依赖于线程对象。

上代码!
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们看到程序崩溃了,什么原因?
当我们程序进行执行时,进入到主函数,我们给这个进程分配了资源:代码资源,fun函数,主函数都是代码资源,还有数据区,还有我们的堆区,栈区。
在Linux2.6以后的版本,当我们进入主函数,创建一个线程叫做主线程。
在这里插入图片描述
我们的主函数变成主线程,主函数由两部分构成:一部分是分配给主线程的栈,一部分是主线程的信息部分。我们在主线程的栈定义一个x值,创建了一个线程对象t1,我们要创建t1线程对象,拥有和主线程一样的资源,有自己的线程信息和自己的线程栈。
在这里插入图片描述
程序接着向下执行到睡眠函数。睡眠的目的是使得主线程把CPU资源让步出来。
我们的t1线程开始执行,到达进程找到fun代码,执行在t1线程栈帧上。在t1线程栈帧开辟空间,定义i,a,打印a,给出睡眠200毫秒,接着打印,睡眠,当这个线程执行完毕之后,并不意味着线程对象销毁,线程对象依然存在,我们回退到主线程,主线程结束,但是t1线程对象没有结束,所以系统会报错。
所以我们要这个函数:jion();
在这里插入图片描述
这个函数作用不但是等待当前线程完成其执行,而且更重要的目的是当线程执行完对应的函数之后,我们把线程对象对应的资源给释放。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
第一个参数是函数的地址,第二个参数是线程的参数,把x给a变量。
如果线程函数没有参数
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
执行没问题!
我们增加代码:再创建一个线程!
在这里插入图片描述
在这里插入图片描述
会不会打印出6,7,8,9?
答案是不可能的!!!
当我们程序执行的时候,进入到主函数,相当于进程,我们给进程分配了代码区,数据区,栈区,堆区;这个栈给给主函数,这个主函数变成主线程,有主函数的栈帧和主函数的线程对象两部分。我们创建t1线程对象,也有两部分构成:栈和t1线程信息。我们创建t2线程对象,也有两部分构成:栈和t2线程信息。
在这里插入图片描述
虽然是一份funa函数创建两份线程。
我们向下执行,主线程执行睡眠。线程和进程一样,有就绪,执行,睡眠,阻塞。主线程让步CPU资源。t1,t2线程运行,调动funa函数,这个函数只有一份。我们在线程t1去调动funa时候,这个函数在t1的栈空间调动,在线程t1定义x,x++;我们有可能睡眠之后,t2线程执行,调动funa函数,在t2的栈空间定义x,x++,这2个x是不一样的,在不同的栈空间中。不管怎么打,有可能是乱序,但是不可能是突破4的。
在这里插入图片描述
我们创建多个线程,可以共享同一份函数,但是函数的局部变量是在每个线程中独立存在,互不关系。不需要加互斥量哦!

我们接着往下看

在这里插入图片描述
这个有没有可能打印5,6,7,8,9?
答案是可能的!因为这是个全局量。
我们从主函数执行,我们给进程分配代码区,全局变量区,栈区,堆区。
当我们主函数执行,产生主线程对象,创建t1线程对象,有t1自己的栈,信息,我们创建t2线程对象,有t2的栈和信息。一旦被创建,就有被调动的可能性。没有睡眠函数,依旧可以调动。当我们执行t1线程,在ti空间调动funa函数,但是++的是对全局对象,++是全局量。

我们的g_max有可能加不到9
线程1和线程2同时对全局变量(比如是1)取值++了!然后一起把2返回了。对g_max++有三条汇编语句,不是原子操作。
在这里插入图片描述
这个全局变量被多个线程对象共享。要么进行原子性,要么进行加锁。

我们接着看。
如果线程函数参数是指针呢?
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
线程是可以这样的。
我们不能让主函数先死再执行线程funa,就变成失效指针了。

如果线程函数参数是引用呢?
在这里插入图片描述
在这里插入图片描述
接着往下看

类的成员函数线程化问题

在这里插入图片描述
在这里插入图片描述
执行一下
在这里插入图片描述
如果都对value值处理呢?
在这里插入图片描述
在这里插入图片描述
运行程序
在这里插入图片描述
我们传递的obj都是一个个的副本。
我们打印this指针看一下
在这里插入图片描述
在这里插入图片描述
当线程化t1的时候,传入obj,建立obj的副本,以此类推。
我们把构造函数和拷贝构造函数给出来看看
在这里插入图片描述

在这里插入图片描述
我们拷贝了3次函数。
我们将要线程化,obj构建临时对象参与。对value++是对副本++,不会影响obj。

这里的thread函数,第一个参数是线程化的函数名,第二个是对象名,第三个是传入的参数。

在这里插入图片描述
声明成静态函数,thread构建时候,不用传对象进去,因为静态函数没有this指针。
在这里插入图片描述
在这里插入图片描述

仿函数线程化

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
创建线程传入的参数对象取地址会是怎么样的?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
加个&进去看看
在这里插入图片描述
把当前对象的地址传进去给this指针了。
在这里插入图片描述

线程之间不能互相赋值和拷贝

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
但是可以进行移动赋值!
在这里插入图片描述
移动赋值,资源转移!t2线程资源给t1,t2的线程释放了。
在这里插入图片描述
所以线程函数有移动构造函数和移动赋值函数
在这里插入图片描述

分离线程(detach)

在这里插入图片描述
线程的分离。
在这里插入图片描述
在这里插入图片描述
运行程序
在这里插入图片描述
主线程执行完毕。
程序进入主函数,我们分配了一个进程,有代码区,数据区,栈区,堆区。进入到主函数,分配主线程,在主线程创建t1线程,对应于线程对象t1,当我我们t1.detach的时候,t1和线程对象没关系了,主程序执行完毕,不管子线程是否执行完毕,都将撤销这个子线程的资源。
在这里插入图片描述
一旦分离意味着离婚了,没有关系了。
在这里插入图片描述
在这里插入图片描述
这种可能性也是存在的!

线程swap

在这里插入图片描述
t1资源和t2资源交换
如果t1没有资源,就是t2资源给t1
在这里插入图片描述
在这里插入图片描述
句柄相当于id号

返回线程的id号

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
主线程的ID号也可以打印。
当我们程序执行,进入主函数,给进程分配空间,创建主线程对象,填写主线程的信息包括ID号。子线程也是。
我们创建t1线程,有自己的栈空间,ID号。
我们创建t2线程,有自己的栈空间,ID号。
当我们继续执行,取t1,t2的ID号。这个全局函数get_id是运行在各自的线程空间中。我们可以认为是把当前线程信息传递进去的。
在这里插入图片描述
这个静态函数是返回内核CPU的个数。
在这里插入图片描述
在这里插入图片描述
但是打印的是12。
返回的是虚拟内核数

线程joinable函数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
活跃和不活跃并不指的是你是否把程序执行完,指的是你的线程对象是否存在,如果线程对象存在就是活跃,如果线程对象不存在就是不活跃!

C11不可以获取线程返回值

没有办法通过retur获得!
C11没有给接口函数,我们只能继承C11然后增加函数。

线程加锁

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
原因是打印的时候线程互相侵占!
我们加入互斥器!

在这里插入图片描述在这里插入图片描述
但是我们不能保证先打印a还是b,次序保证不了,保证的是线程1打印的时候其他线程不能进行打印!
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
RAII(资源获取即初始化)
在这里插入图片描述
我们创建对象,在对象里面加锁,函数执行完,要销毁,解锁。基于智能指针,构造函数用于获取资源,析构函数用于释放资源!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林林林ZEYU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值