C++中的多线程方法:std、boost、pthread、windows api等;每个库都有自己的线程封装和设计方式。
一、C++11 std::thread
优点:原先使用多线程只能用系统的API,无法解决跨平台问题,一套代码平台移植,对应多线程代码也必须要修改。现在在C++11中只需使用语言层面的thread可以解决这个问题。
缺点:
-
编译器兼容性:使用C++11特性需要编译器支持,特别是gcc编译器版本需要大于4.8,并且在编译时需要加上参数-std=c++11 -lpthread。这意味着,在一些较旧的编译环境中,开发者可能无法使用std::thread,或者需要更新编译器和编译参数,这增加了使用的门槛1。
-
学习成本:多线程编程本身具有一定的学习曲线,std::thread的引入虽然简化了多线程的使用,但对于初学者来说,仍然需要一定的时间来理解和掌握。此外,与操作系统提供的线程接口(如pthread)相比,std::thread虽然更方便,但在某些特定场景下,pthread可能提供更细粒度的控制2。
-
项目需求:并非所有项目都需要多线程编程。对于一些小型项目或者简单的任务分配,使用多线程可能并不必要,因此std::thread在这些场景下自然不会被采用。而对于需要高性能计算或者并发处理的大型项目,虽然std::thread是一个不错的选择,但项目的其他需求和技术栈可能会限制其使用。
1.1 创建线程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
在上面的代码中,通过 std::thread t1(foo)
创建了一个新线程,并在新线程中执行了函数 foo
。
1.2 线程管理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
在上面的代码中,通过调用 t1.join()
可以等待线程 t1
结束,并通过调用 t1.detach()
可以分离线程 t1
,使线程在后台运行。
std::thread::detach()
方法是分离线程的方法,通过调用 detach()
方法,可以让线程在后台独立运行,不需要等待线程结束即可返回。与调用 join()
方法不同,分离的线程不受父线程的控制,因此如果父线程结束,分离的线程不会因此结束。请注意,分离的线程一旦开始执行,它将独立运行,不受任何控制,因此不能在父线程中等待它的结束或者通过其他方式获取其结果。如果需要等待线程结束,请使用 join()
方法。
分离线程的主要作用是让线程在后台独立运行,不需要等待线程结束即可返回。这样可以在不需要等待线程结束的情况下,在父线程中执行其他任务,从而提高程序的效率。
1.3 传递参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
在上面的代码中,通过在创建线程时传递参数 10
,并在函数 foo
中读取参数,实现了在线程中传递参数的功能。
1.4 线程间通信
1.4.1 使用共享变量和互斥量(互斥锁):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
我们定义了一个全局变量g_num,两个线程分别运行print_num函数。print_num函数不断地对g_num变量进行读写操作,并使用互斥量g_num_mutex对该变量进行加锁。这样可以确保在每次读写操作时,不会有其他线程访问g_num变量。如果g_num的值已经大于等于100,则表示线程退出。最后主线程调用join函数,等待其他线程退出。
1.4.2 使用共享内存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
1.5 其他线程相关信息
std::thread::hardware_concurrency()
:返回当前系统支持的最大线程数。std::thread::native_handle()
:返回线程的原生句柄,在不同的平台中可能不同。std::thread::joinable()
:判断线程是否可以被 join,如果线程已经结束或者被分离,则返回 false。std::thread::join()
:等待线程结束,直到线程结束才返回。std::thread::detach()
:分离线程,使线程可以在后台运行,并且不需要等待其结束。std::thread::get_id()
:返回线程ID。
二、boost多线程库
Boost Thread库是跨平台的,它可以在不同的操作系统上运行,包括Windows、Linux、Mac等。这是因为Boost库的设计考虑了跨平台兼容性,使得开发者能够在不同的操作系统上使用相同的代码基础来实现多线程编程。Boost Thread库通过封装底层操作系统的线程API,提供了一组统一的接口,使得开发者可以更容易地编写多线程程序,而无需关心底层操作系统的差异。这种跨平台的设计使得Boost Thread库成为了一个广泛使用的多线程解决。
官方文档:
Boost 库中的 boost::thread
类可以方便地创建和管理多线程。以下是一个使用 Boost 库中的 boost::thread
类创建多线程的简单示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
三、POSIX线程(Linux&Unix)
Pthreads最初是为Unix-like系统设计的(系统的API),如Linux和Solaris,但也有在Windows上实现的版本,如pthreads-w32。
C++ POSIX 线程(pthread)库可以帮助您在 C++ 中创建和管理多线程。下面是一个创建和启动一个新线程的示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
这段代码中,pthread_create
函数用于创建一个新线程,并启动它。第一个参数是一个指向线程 ID 的指针,第二个参数指定了线程的属性,通常为 NULL
,第三个参数是线程函数的地址,最后一个参数是传递给线程函数的参数。
pthread_join
函数等待线程结束,第一个参数是线程 ID,第二个参数是接收线程返回值的指针,通常为 NULL
。
四、 Windows线程库
4.1 线程使用
下面是使用Windows API创建线程并打印数字并获取重要的线程信息的代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
4.2 线程通信
在 Windows API 中,可以使用 CreateThread
函数创建线程,以下是通过共享变量实现线程间通信的代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
|
在主函数中,我们调用了 CreateThread
函数创建了两个线程,将共享变量 sharedVariable
的地址作为参数传入。线程 1 和线程 2 都通过判断共享变量的值来实现通信,它们每当共享变量的值变化时都会输出当前的值。
在这个例子中,WaitForMultipleObjects函数将等待两个线程hThread1和hThread2完成,并且要求等待所有事件对象完成,因此参数bWaitAll的值为TRUE。并且dwMilliseconds的值为INFINITE,所以等待时间是无限的。
以上:原文链接:C++创建多线程的方法总结_C 语言_脚本之家