第一节 并发基本概念及实现,进程、线程基本概念:
(1)并发、进程、线程的基本概念和综述:
(1.1)并发:
并行:两个或者更多的任务(独立的活动)同时发生(进行):一个程序同时执行多个独立的任务;
以往计算机,单核cpu(中央处理器):某一时刻只能执行一个任务:由操作系统调度,每秒钟进行多次所谓的“任务切换”。
并发的假象(不是真正的并发);这种切换(上下文切换)是要有时间开销的。比如操作系统要保持你切换时的各种状态,执行进度等信息,都需要时间,一会切换回来的时候要复原这些信息。
硬件发展,出现了多处理器计算机:用于服务器和高性能计算领域。台式机:在一块芯片上有多核(多个)cpu:双核,4核,8核,10核。能够实现真正的并行执行多个任务(硬件并发);
并行是多个任务在多个核心上执行,并发是多个任务在一个核心上执行、
使用并发的原因:主要就是同时可以干多个事,提高性能。
(1.2)可执行程序:
磁盘上的一个文件,Windows下,一个扩展名为 .exe的。 linux,ls -ls,rwxrwxrwx(x执行权限);
(1.3)进程:
大家已经知道了可执行程序是能够运行,Windows下,双击一个可执行程序来运行。 linux下 ./文件名 ./a 进程,就是一个可执行程序运行起来了,就叫创建了一个进程。进程,就是运行起来的的可执行程序。
(1.4)线程:
a)每个进程(执行起来的可执行程序),都有一个主线程,这个主线程是唯一的,也就是一个进程中只能有一个主线程。
b)当你执行要给可执行程序,产生了一个进程后,这个主线程就随着这个进程默默的启动起来了;
ctrl+f5运行这个程序的时候,实际上是进程的主线程来执行(调用)这个main函数中的代码;主线程与进程唇齿相依,有你必有我,有我必有你,没有我必然没有你。线程:用来执行代码的。线程这个东西,理解成一条代码的执行通路(道路);
除了主线程之外,我们可以通过自己写代码来创建其他线程,其他线程走的是别的道路,甚至取不同的地方。我每创建一个新线程,我就可以在同一时刻,多干一个不同的事(多走一条不同的代码执行路径)。
多线程(并发):线程并不是越多越好,每个线程,都需要一个独立的堆栈空间(1M),线程之间的切换要保存很多中间状态;切换会耗费本该属于程序运行的时间;
(1.5)学习心得:
(2)并发的实现方法:
(2.1)多进程并发:
(2.2)多线程并发:
(2.3)总结:
(3)C++11新标准线程库:
第二节:线程启动、结束,创建线程多法、join,detach:
(1)范例演示线程运行的开始和结束:
第四行后面:,就代表着我们这个线程运行结束。
第七行后面:主线程一直保持 运行,不要让主线程运行完毕。
住了,另外一条线还是可以通行的。这就是多线程;
因为子线程函数小速度快,比i jove china先打印结束
(1.1)thread:
入口函数在代码段,内存里只有唯一的指令,编译器编译后,这只是个在代码段中入口函数的起始指令地址
(1.2)join():
加入/汇合,说白了就是阻塞,阻塞主线程,让主线程等待子线程执行完毕,然后子线程和主线程汇合,然后主线程再往下走。
阻塞主线程并等待myprint子线程执行完、
mytobj . join(); //主线程阻塞到这里等待myprint()执行完,当子线程执行完毕,这个join()就执行完毕,主线程就继续往下走。
(1.3)detach():
detach:分离,也就是主线程不和子线程汇合了,你主线程执行你的,我子线程执行我的,你主线程也不必等我子线程运行结束,你可以先执行结束,这并不影响我子线程的执行。
为什么引入detach():我们创建了很多子线程,让主线程逐个等待子线程结束,这种编程方法不太好,所以引入了detach。
detach()会使线程myprint失去我们自己的控制。
detach相当于主线程退出后,子线程由操作系统接管执行完毕再杀死;传统多线程程序主线程要等待子线程执行完毕,然后自己再最后退出;
(1.4)joinable():
判断是否可以成功使用join()或者detach()的;返回true(可以join或者detach)或者false(不能join不能detach)。
(2)其他创建线程的手法:
(2.1)用类,以及一个问题范例:
只要想thread参数只能传函数,想要类的话就Operator(),变成"函数",本质是那个thread需要一个函数指针做参数。
第三节:线程传参详解,detach()大坑,成员函数做线程函数:
(1.1)要避免的陷阱(解释1):