
c++多线程
黑川赤音
如有疑问或者需要代码,可以评论区留下邮箱或者私信
展开
-
atomic原子操作
理论上来说,应该是200000,但是最后结果不是200000。这是多个线程同时操作一个全局变量引起的错误。原子,在化学中意味着不可再分,在编程中就意味着操作不可被打断。只要把原子操作作用在代码段里。当一个程序中的两个线程同时向这个程序里的全局变量增加数时会发生什么?这样就可以成功,但是这样会增加运行的时间。互斥操作作用在语句上,而原子操作作用在变量上。此时,引入原子操作。原创 2023-07-04 20:39:56 · 195 阅读 · 0 评论 -
限时等待的互斥量
起到了设置了一个限时等待锁。for循环里面时打印10次字符串,每次打印输出后延时1s。那么其就延时了10s。但是显然无法上锁成功,因为线程1占据了10s。fun2中,第28行休眠2秒,让线程1先占据资源。代表等待5s,如果5s内上锁成功了,就执行。本文结束一种新的锁,称为。为时间互斥锁,即可以起到限时等待的作用。原创 2023-07-04 20:01:00 · 158 阅读 · 0 评论 -
通过函数指针来创建线程
可以正确输出Hello World,线程1运行结束后线程2还要运行。等线程1和线程2都执行完毕后,主线程才要继续执行。只输出了8个hello world,这是因为主线程结束了,然而子线程还没有结束。注意:要避免引用修改字符串常量,方法是在前面+const。把main函数作为主线程,hello做为子线程。此时就需要我们让主线程等一会子线程。原创 2023-06-21 12:03:54 · 119 阅读 · 0 评论 -
c++多线程并发简介
c++11之后,其本身自带的标准库就已经支持多线程了。c++11相当于一个分水岭。单核处理器同一时刻只能执行一个任务。双核处理器能同时处理两个任务。单核处理器是在高速的切换其执行的程序,实现宏观的多任务并发,这只是一个假象。从硬件理论上来说,其最多能执行64个线程。当你只有8个核心时,想同时执行16个程序,那么我们要同时使用硬件并发和任务切换。原创 2023-06-21 00:18:38 · 278 阅读 · 0 评论 -
如何记录程序运行时间
使用模板类: chrono::duration前面的int限定了延时单位是一个整数。只要1小时,2小时,但是没有1.5小时。ratio代表一个分数。后面的2代表分母,前面的1为分子。如果我希望其延时10s。只需ratio(20),即0.5×20=10秒。那么如下:ratio(5)就代表了延时5分钟。第19行是开始和结束的时间差,表示运行的持续时间。起到了强制类型转换的作用,其是一个模板类。表示返回的是系统当前的高精度时间。原创 2023-07-03 22:10:42 · 285 阅读 · 0 评论 -
限时等待
还有一种等待状态叫做延时等待,如果如果我去吃饭,但是饭店已经客满,需要排号,当排到我号时,饭店会叫我,如果我不在,饭店会等我五分钟,如果五分钟内我没来,那饭店就把我跳过,此时这5分钟就叫做延时等待。延时等待也有两种方式,上面的叫做延迟超时,还有一种叫做绝对超时,就是我约你8点见面,我最多等待到8点10分。这种等待叫做绝对超时。如果一个线程要等待的线程的目标没有实现,那么他会一直等下去,此时就陷入了阻塞等待。如上图所示:第29行if语句表示如果等10秒钟,还没有等到结果,那么就不等了。原创 2023-07-03 21:28:58 · 252 阅读 · 0 评论 -
packaged_task创建异步任务
首先使用函数模板类:创建一个对象,是一个任务包。这个任务包是未来(future)的基础。然后建立用函数模板类建立future类。之后建立future和packaged_task的联系。功能主要是做了求两数之和,然而一般情况下,我们并不习惯这样编写子函数,更习惯直接return x+y;所以有了packaged_task。之后创建线程,move的目的是将pkt这一个类转移到t线程里面去。当然:也可以用lambda表达式来实现类似的任务,为什么要有packaged_task?其主要作用是简化对子函数的要求。原创 2023-07-01 17:28:28 · 178 阅读 · 0 评论 -
promise的创建
同过future和promise来实现线程间的通信,不需要使用互斥量和条件变量等。以上是介绍了主线程与子线程之间的通信,下面介绍子线程与子线程之间的通信。有承诺才有未来,承诺做为一个参数,承诺的东西做完之后,才会有未来。promise(承诺)<------> future(未来)promise像是一个容器,来承接参数。原创 2023-06-30 22:10:57 · 296 阅读 · 0 评论 -
async异步任务_同步任务选项
async里面有三个参数,一个是成员函数的地址,第二个是 类,第三个是传入的参数。让类里面的一个成员函数当作线程的参数。接下来介绍async的同步线程创建。原创 2023-06-30 21:21:42 · 200 阅读 · 0 评论 -
async创建异步任务
sync为同步的意思,async为异步任务。同步任务前文已经结束过:他指的是两个人协同完成一个任务。如我要问某一个学霸同学数学题,学霸同学先帮我看一下数学题,在告诉我,我在那。之前一直采用的是全局变量+互斥锁的方法。到目前为止,线程运行完之后还无法提供一个返回值。async创建完线程之后开始执行线程里面的函数,此时并不会阻塞主线程的执行。创建异步任务就用async,其是一个异步的函数模板。而异步任务是,学霸同学在帮我看数学题的同时,,等学霸同学看完之后我再去做之前那个题。学霸同学看完教我,这叫做同步任务。原创 2023-06-30 11:26:30 · 174 阅读 · 0 评论 -
条件变量wait的另一种形式
flag.wait()里面可以有两个参数,第一个是锁,第二份一般是lambda表达式之类的谓词,其返回值一般是bool类型。此时由于lambda表达式返回不为真,所以此时仍在等待。此时lambda表达式就算正常的。原创 2023-06-29 21:53:12 · 171 阅读 · 0 评论 -
线程同步示例--生产者和消费者
消费者消耗完生产者的产物之后,在通知生产者生产。生成者生产出来之后通知消费者说可以消费了。原创 2023-06-29 21:13:41 · 251 阅读 · 0 评论 -
线程并发同步--条件变量--conditional_variable
显然因为线程1睡了5秒,是线程2霸占了玩具A, 但是线程2在霸占玩具A之后要等待信号A才能继续往下走,但是信号A由线程1发出,线程1只有霸占了玩具A才能发处信号A,显然,此时线程1无法霸占玩具A,因为其已经被线程2霸占了。当线程2的while循环内第一次运行结束之后,开始进行第二次时,他想要霸占玩具A,但此时玩具A被线程1霸占 ,线程2无法进入第76行等待,也就无法进行下去了。如果线程2能在等待信号A的同时解除对玩具A的霸占就好了:此时就是flag.wait()有这个功能,可以在等待的同时解除霸占。原创 2023-06-29 20:35:57 · 220 阅读 · 0 评论 -
如何避免死锁--方法三--scoped_lock
scoped_lock是c++17新增的一种模板,也是RAII模式。其是可变参数,可以接受各种互斥类型作为参数模板,可以指定多个互斥量。为什么可以将模板类的参数列表省略?因为c++17标准增加了根据参数的个数和类型来推导模板类里的参数列表。前文中我们说到,lock可以锁定多个互斥量,scoped_lock也可以做到。其是一个模板类,可以指定参数。原创 2023-06-29 18:58:29 · 286 阅读 · 0 评论 -
如何避免死锁——方法2_ubique_lock
unique_lock<mutex> 大部分情况下可以和lock_guard<mutex>替换。但是前者更灵活,同时也占用了更多的内存资源。unique_lock也是一个模板类。原创 2023-06-28 22:07:27 · 196 阅读 · 0 评论 -
死锁的产生
死锁的产生:有一个公共区的玩具,A和B想玩,但是A先得到了玩具,A玩完玩具之后又去干别的事情,但是并没有把玩具还回去,此时B就玩不到了玩具,在无限期的等待。如果有一套玩具:比如鼓和敲鼓的锤子,A获得了鼓,B获得了锤,但是他们俩都不想放弃自己手里的玩具。A和B都永远玩不了敲鼓,在无限期等待。这也是一种死锁的情况。线程1把num资源给占用,线程2一直没办法获得num,线程2用于卡住了,与此同时,主线程的合流无法执行。注意:这里的资源a和b各对应一把锁。原创 2023-06-28 20:55:32 · 135 阅读 · 0 评论 -
避免游离指针或引用以保护共享数据
用游离指针实现了修改,这是我们不想要的。因为function(data)将锁所在的作用域范围之外传递了引用和指针。这样看上去是没什么问题,将变量卡在私有接口上上,并且用锁将变量卡到一个进程中。在对共享数据进行保护时,有可能被外界的指针修改。这种方法并没有被制止的方法,只能让我们写代码时不要这样做。原创 2023-06-27 21:55:37 · 151 阅读 · 0 评论 -
在多线程中使用互斥
在共享资源时可能会出现一些问题,线程之间的共享数据不仅仅是读数据,有很多情况都是写入数据,如果某一个线程改变了共享数据,会对其他线程有影响。还有一些时候,一个线程在写入数据时,不希望其他线程也写,也就是说在我修改某个数据时,不希望其他人也修改这些数据。所以引入互斥锁,互斥锁就是在我上厕所时会把厕所上一个锁,其他人不能上厕所。直到我上完厕所,解除标记,其他人就能上厕所了。虽然这些线程是在同时运行,但是lock_guard将其后面的东西占用,只有当一个线程占用结束之后另一个线程才能占用ivec。原创 2023-06-27 20:15:43 · 126 阅读 · 0 评论