C++ std::thread的定义和功能
std::thread是C++11引入的标准库类,用于创建和管理线程。通过std::thread,程序可以并发执行多个任务,从而提高效率。
功能与作用:
- 创建线程:可以启动一个线程执行某个函数或任务。
- 管理线程:允许主线程与子线程进行交互,如等待线程结束(join())或分离线程(detach())。
- 提高性能:利用多核处理器的能力并行处理。
主要成员函数:
- std::thread::join(): 阻塞调用线程,直到被管理线程完成。
- std::thread::detach(): 分离线程,使其在后台运行。
- std::thread::joinable(): 检查线程是否可被join()或detach()。
std::thread 参考代码一
#include <iostream>
#include <thread>
#include <chrono>// 模拟任务函数
void print_numbers(const std::string& thread_name, int start, int end) {for (int i = start; i <= end; ++i) {std::cout << thread_name << " prints: " << i << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟延迟}
}int main() {std::cout << "Main thread starts." << std::endl;// 创建两个线程std::thread thread1(print_numbers, "Thread 1", 1, 5);std::thread thread2(print_numbers, "Thread 2", 6, 10);// 检查线程是否joinableif (thread1.joinable() && thread2.joinable()) {std::cout << "Both threads are joinable." << std::endl;}// 主线程等待子线程结束thread1.join();thread2.join();std::cout << "All threads completed. Main thread exits." << std::endl;return 0;
}
std::thread 参考代码一输出结果
运行后程序会交替打印两个线程的输出:
Main thread starts.
Both threads are joinable.
Thread 1 prints: 1
Thread 2 prints: 6
Thread 1 prints: 2
Thread 2 prints: 7
Thread 1 prints: 3
Thread 2 prints: 8
Thread 1 prints: 4
Thread 2 prints: 9
Thread 2Thread 1 prints: prints: 105All threads completed. Main thread exits.
备注:
Linux 系统通过 g++ thread.cpp -o thread -lpthread 进行编译
代码一分析
- std::thread对象的创建:
std::thread thread1(print_numbers, "Thread 1", 1, 5);
启动线程thread1,执行print_numbers函数,传递参数。
2. 等待线程结束:
thread1.detach();
join()阻塞主线程,直到thread1完成。
3. 分离线程(可选):
thread1.detach();
线程独立运行,不再由主线程管理。
4. 线程同步:
使用std::cout时,为了避免多线程输出交错,可以加锁(未示范)。
std::thread 参考代码二
#include <iostream>
#include <thread>using namespace std;int main() {auto func1 = []() {for (int i = 0; i < 10; ++i) {cout << i << " ";}cout << endl;};std::thread t1(func1);if (t1.joinable()) {t1.detach();}auto func2 = [](int k) {for (int i = 0; i < k; ++i) {cout << i << " ";}cout << endl;};std::thread t2(func2, 20);if (t2.joinable()) { // 检查线程可否被joint2.join();}return 0;
}
std::thread 参考代码二输出结果
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
代码二分析
上述代码中,函数func1和func2运行在线程对象t1和t2中,从刚创建对象开始就会新建一个线程用于执行函数,调用join函数将会阻塞主线程,直到线程函数执行结束,线程函数的返回值将会被忽略。如果不希望线程被阻塞执行,可以调用线程对象的detach函数,表示将线程和线程对象分离。
如果没有调用join或者detach函数,假如线程函数执行时间较长,此时线程对象的生命周期结束调用析构函数清理资源,这时可能会发生错误,这里有两种解决办法,一个是调用join(),保证线程函数的生命周期和线程对象的生命周期相同,另一个是调用detach(),将线程和线程对象分离,这里需要注意,如果线程已经和对象分离,那就再也无法控制线程什么时候结束了,不能再通过join来等待线程执行完。
下面是对thread进行封装,避免没有调用join或者detach可导致程序出错的情况出现:
std::thread 参考代码三
#include <iostream>
#include <thread>class ThreadGuard {public:enum class DesAction { join, detach };ThreadGuard(std::thread&& t, DesAction a) : t_(std::move(t)), action_(a){};~ThreadGuard() {if (t_.joinable()) {if (action_ == DesAction::join) {t_.join();} else {t_.detach();}}}ThreadGuard(ThreadGuard&&) = default;ThreadGuard& operator=(ThreadGuard&&) = default;std::thread& get() { return t_; }private:std::thread t_;DesAction action_;
};int main() {ThreadGuard t(std::thread([]() {for (int i = 0; i < 10; ++i) {std::cout << "thread guard " << i << " " << std::endl;}std::cout << std::endl;}), ThreadGuard::DesAction::join);return 0;
}
std::thread 参考代码三输出结果
thread guard 0
thread guard 1
thread guard 2
thread guard 3
thread guard 4
thread guard 5
thread guard 6
thread guard 7
thread guard 8
thread guard 9
C++11还提供了获取线程id,或者系统cpu个数,获取thread native_handle,使得线程休眠等功能
std::thread 参考代码四
#include <iostream>
#include <thread>using namespace std;int main()
{auto func = [](){for (int i = 0; i < 10; ++i){cout << i << " ";}cout << endl;};std::thread t(func);if (t.joinable()){t.detach();}cout << "当前线程ID " << t.get_id() << endl;cout << "当前cpu个数 " << std::thread::hardware_concurrency() << endl;auto handle = t.native_handle(); // handle可用于pthread相关操作std::this_thread::sleep_for(std::chrono::seconds(1));return 0;
}
std::thread 参考代码四输出结果
当前线程ID thread::id of a non-executing thread
当前cpu个数 4
0 1 2 3 4 5 6 7 8 9