前言
c++11开始支持多线程,使得编写c++多线程程序无需依赖特定的平台,使开发者能够编写可移植的、行为确定的多线程程序代码。
什么是并发
所谓并发,是两个或多个同时独立进行的活动。而计算机中的并发,是指同一个系统中,多个独立活动同时进行。
对于单核处理器,在同一时刻,只能处理一个任务,操作系统将一个时刻分成若干时间片,在每个时间片上执行一个任务,从而实现“伪并发”。对于多核处理器,从硬件上支持并发,在同一时刻内能够运行多个任务,我们称之为硬件并发。
并发的方式:多进程并发、多线程并发。
多进程并发
将一个应用软件拆分成多个独立进程同时运行,这些独立进程都只包含一个主线程。这些独立的进程可以通过操作系统提供的API事件进程间通信(套接字、管道、文件、剪切板)。
优点:相互独立,数据资源互不受影响,容易编写出安全的并发代码。
缺点:开销大,需要为每个进程分配资源;进程间通信速度慢,操作复杂。
多线程并发
多线程并发是指在单一进程中运行多个线程,每个线程独立运行,线程间通过共用相同的地址空间,从而实现在线程间通信。
优点:开销低
缺点:操作复杂
并发与并行
并发:主要关心的是分离关注点或响应能力。
并行:主要关心的是利用可调配的硬件资源提升大规模数据处理的性能。
为什么需要使用并发
使用并发的主要原因有:分离关注点、提升性能。
分离关注点
编写软件时,分离关注点几乎总是不错的构思:归类相关代码,隔离无关代码,使程序更易于理解和测试,因此所含缺陷很可能更少。可以将一个应用软件划分成如下几个线程:一个UI线程、一个网络线程、一个数据库读写。各个线程之间相互独立,数据访问通过开放接口实现,从而实现各模块代码各自管理。
提升性能
增强性能的并发方式有两种:
- 第一种是将单一任务分解成多个部分,各自并行运作,从而节省总运行耗时。
- 第二种是利用并行资源解决规模更大的问题。例如,只要条件适合,便同时处理2个文件,或者10个,甚至20个,而不是每次1个。同时对多组数据执行一样的操作,实际上是采用了数据并行,其着眼点有别于任务并行。采用这种方式处理单一数据所需的时间依旧不变,而同等时间内能处理的数据相对更多。
何时避免使用并发
收益不及代价。多数情况下,采用了并发技术的代码更难理解,编写和维护多线程代码会更劳心费神,并且复杂度增加可能导致更多错误。编写正确运行的多线程代码需要额外的开发时间和相关维护成本,除非潜在的性能提升或分离关注点而提高的清晰度值得这些开销,否则别使用并发技术。
并发与C++多线程
早年C++并不支持多线程,程序员若想使用多线程,必须使用平台提供的API,缺点是依赖特定平台,不便跨平台开发;二是可能依赖特定的处理器架构。
c++11开始支持多线程,规定了内存模型,提供多线程操作,线程管控、保护共享数据,线程间同步以及底层原子操作功能。使得开发者摆脱了平台依赖,仅用C++即可写出高效的代码。
若要实现某项功能,代码可以借助高级工具,或者直接使用底层工具。两种方式的运行开销不同,该项差异叫作抽象损失。在绝大数主流平台,C++多线程是低抽象损失。如果开发者追求极致性能,C++也专门提供了相关接口,开发者可以自行开发出高效的多线程程序。通常不建议。
实例
1 #include <iostream>
2 #include <thread>
3
4 void hello()
5 {
6 std::cout << "Son Thread " << std::this_thread::get_id() << std::endl;
7 std::cout << "Hello World!\n";
8 }
9
10 int main()
11 {
12 std::cout << "Main Thread " << std::this_thread::get_id() << std::endl;
13 std::thread th(hello);
14 th.join();
15 }
程序第2行引入头文件<thread>,要使用多线程必须包含该头文件。
在main()函数中,std::this_thread是一个命名空间,在该命名空间中包含获取当前线程相关信息的接口,程序中用get_id()函数获取当前线程的线程ID,用做区分。
要启动一个线程,需要定义一个std::thread对象,该对象需要传递一个可调用对象,作为线程的起始函数,hello()函数就是th线程对象的起始函数。
join()函数的作用的等待子线程执行完毕,主函数会阻塞在此处等待子线程结束。如果不调用join()函数,程序将出现异常情况。
hello()函数是线程的入口函数,线程启动后,最先执行的函数就是hello()函数。
Copyright
本文参考至《c++并发编程实战》 第二版,作者:安东尼·威廉姆斯。本人阅读后添加了自己的理解并整理,方便后续查找,可能存在错误,欢迎大家指正,感谢!