多线程(multithreading),是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程,进而提升整体处理性能。
具有这种能力的系统包阔对称处理机、多核心处理器以及芯片级多处理或同时多线程处理器。在一个程序中,这些独立运行的程序片段叫作“线程”(Thread),利用它编程的概念就叫作“多线程处理”。
C++多线程编程框架有很多,以下是一些常用的:
- POSIX Threads(pthread):pthread是C/C++常用的跨平台线程库,支持多个线程和进程之间的共享存储器;
- C++11标准库中的std::thread:C++ 11标准库中引入了线程支持,并定义了一组线程头文件和类库;
- Boost C++ Libraries中的boost::thread:boost::thread是一个开源的跨平台C++多线程库,支持线程创建、等待、关联、分离、互斥量、条件变量、递归锁等功能;
- OpenMP:是一种基于共享内存的并行编程模型,在应用程序中通过指令来对代码进行并行化处理。支持多线程的编译器可以自动将代码转换为使用多线程,简单易用;
- TBB (Intel Threading Building Blocks):是C++多核心并行编程框架,包含线程和数据的并行执行和管理的类和函数库,适用于任务级并行并提供负载均衡,以及防止数据竞态和死锁的同步机制。
以上是一些常用的C++多线程编程框架,根据不同需求选择合适的工具,可以更好地提高代码效率和运行速度,从而实现更好的应用程序性能。
1、Linux pthread
pthread是POSIX线程标准库的一部分,它提供了一套C语言函数库,用于在多线程程序中创建、同步和控制线程。在C++中也能使用pthread库。
以下是pthread库的一些常用函数:
- pthread_create():用于创建一个新线程,并指定线程入口函数、传递给函数的参数。
- pthread_join():用于等待一个指定的线程结束,并以指定方式获取其返回值。
- pthread_mutex_init():初始化一个互斥锁对象。
- pthread_mutex_lock():加锁,如果锁已经被占用,则阻塞调用线程。
- pthread_mutex_unlock():释放锁,解除其他线程的阻塞状态。
- pthread_cond_init():初始化一个条件变量。
- pthread_cond_signal():唤醒一个等待在条件变量上的线程。
- pthread_cond_broadcast():唤醒所有等待在条件变量上的线程。
- pthread_cond_wait():等待条件变量的值改变,并且阻塞当前线程。
pthread也支持实现线程局部存储,并支持动态线程操作。通过pthread库,开发者可以更灵活、高效地控制线程的执行流程,实现多线程程序的并发执行。
2、std::thread
std::thread是C++11标准中提供的一种多线程编程库,它与pthread相比具有更加直观和易用的语法。使用std::thread可以通过创建新的线程执行任务,并允许开发者方便地控制这些线程的生命周期,包括创建、等待、分离等。
以下是std::thread库的一些常用方法:
- 构造函数:std::thread支持两种构造方式,一种是默认构造函数,用于创建一个新线程;另一种则是构造函数,用于创建一个新线程并同时指定执行的函数和参数。
- join():等待当前线程退出,并阻塞调用线程。
- detach():将当前线程置为后台运行,与其他线程分离,不再受到主线程控制。
- std::this_thread::sleep_for():使当前线程暂停执行指定的时间。
- get_id():获取当前线程的唯一标识符。
- swap():交换两个线程的状态。
使用std::thread时,需要注意以下几点:
- 在使用join()或detach()之前,必须保证线程已经被启动。
- 线程的状态只能被修改一次,一旦线程被detached或joined,就不能再进行其他操作。
- 在访问共享资源时,需要注意同步问题。
总的来说,std::thread提供了简单、高效的多线程编程方法,使得C++多线程编程更加便捷和易用。
3、boost::thread
boost::thread是Boost C++ Libraries中提供的一个跨平台多线程编程库,它是对C++11标准库std::thread的拓展。boost::thread库与std::thread类似,支持线程创建、等待、关联、分离、互斥量、条件变量、递归锁等功能。
以下是boost::thread库的一些常用方法:
- 构造函数:boost::thread支持两种构造方式,一种是默认构造函数,用于创建一个新线程;另一种则是构造函数,用于创建一个新线程并同时指定执行的函数和参数。
- join():等待当前线程退出,并阻塞调用线程。
- detach():将当前线程置为后台运行,与其他线程分离,不再受到主线程控制。
- sleep():使当前线程暂停执行指定的时间。
- get_id():获取当前线程的唯一标识符。
- yield():将当前线程放弃其时间片,让系统重新分配时间片给其他线程执行。
- interrupt():在线程外部中断正在运行的线程执行。
除了以上常用的方法,boost::thread还包括一些高级特性,例如interruptible_thread、fiber等,用于更加灵活地管理线程执行。总的来说,boost::thread具有良好的可移植性,并且提供丰富的线程控制方法,使得C++多线程编程更加灵活和高效。
4、OpenMP 多线程
OpenMP是一种针对共享内存并行计算的多线程编程标准,它提供了一种简单的方法来实现并行化。OpenMP主要通过添加预处理器指令、库函数和环境变量等方式来实现。
以下是使用OpenMP编写多线程程序的一些常用方法:
- 指定并行区域:使用#pragma omp parallel指令创建一个并行执行的区域。
- 并行执行循环:使用#pragma omp for指令并行执行循环操作。
- 设定线程数目:使用OMP_NUM_THREADS或者omp_set_num_threads函数来设定线程数目。
- 数据分配与同步:使用#pragma omp critical,#pragma omp atomic或者#pragma omp barrier等指令来完成数据分配与同步过程。
- 粒度控制:使用schedule子句来调节粒度,设置任务分配的类型。
- 并行化衡量:使用OpenMP的性能测试工具来衡量并行化的效率,比如perf-report, IACA等工具。
OpenMP使用方便,API简单易学,有着丰富强大的多线程编程功能,而且可以混合使用C++, Fortran, C等语言进行开发,被广泛应用于科学计算、图像处理、实时模拟等高性能计算领域。
5、TBB 多线程
TBB(Threading Building Blocks)是由英特尔公司开发的一个针对多核、分布式处理器的C++多线程并发框架。TBB框架提供了高度抽象化的C++库,让程序猿能够更加容易地将顺序代码转化为并行代码。
以下是TBB框架的一些主要特点:
- 粒度控制:使用Task Scheduler的调度策略可以让用户自然而然地完成任务划分和粒度调整。
- 数据同步:通过原子操作、数据分配、缓存池等技术实现线程间的同步,使得并行执行过程变得更加高效。
- 任务管理:动态调度任务,根据系统负载情况动态调节线程数量,调度未被执行的任务到空闲线程中运行。
- 内存管理:TBB内置各种内存池和缓存池,有效减少了内存碎片,降低了内存分配及回收的时间成本。
- 细粒度锁机制:TBB提供了多种锁机制,包括互斥锁、读写锁、原子操作等,以适应不同的并行场景。
TBB框架相较于传统多线程编程具有很大的优势,它不仅能够实现显式地任务分解,还可以根据任务的大小和系统负载自动调节线程数量,并且具有较低的线程启动和销毁成本。同时,TBB框架提供了平滑且高度抽象化的库接口,使得程序员不必担心过多的底层实现细节,能够专注于编写可移植、快速且高效的并发代码。