C++并发编程:线程启动

发布时间:2024年01月22日

启动线程

C++中构造 std::thread 对象启动线程
void do_some_work();
std::thread my_thread(do_some_work);
? ?最简单的情况下是无参数无返回的函数。启动一个新的线程执行hello()函数。这种函数在其所属线程上运行,函数执行完毕, 线程结束。为了让编译器识别 std::thread 类,需要包含 <thread> 头文件。如同大多数C++标 准库一样, std::thread 可以 将带有函数调用符类型的实例传入std::thread 类中,替换默认的构造函数。
#include<iostream>
#include<thread>
void hello(){
        std::cout<<"Hello Concurrent World\n";
}
int main(){
  std::thread t(hello);
  t.join();
}

在一些情况下,线程运行时,任务中的函数对象需要通过某种通讯机制进行参数的传递,或者执行一系列独立操作;可以通过通讯机制传递信号,让线程停止。

启动了线程,需要明确是要等待线程结束(使用join()),还是让其自主运行。如果 std::thread 对象销毁之前还没有做出决定,程序就会终止( std::thread 的析构函数会调用 std::terminate() )。

创建线程注意点一:

std::thread my_thread(background_task());

这是在声明一个函数而不是在创建一个线程。

这声明了一个名为my_thread的函数,这个函数带有一个参数(函数指针指向没有参数并返回 background_task对象的函数),返回一个 std::thread 对象的函数,而非启动了一个线程。

如果想要启动一个线程,可以这样写:

外面套层小括号

std::thread my_thread((background_task()));
或者使用大括号
std::thread my_thread{background_task()};
或者使用lambda表达式
std::thread my_thread([](){
? ? background_task();
});

创建线程注意点二:如果传入参数的对象中包含的指针和引用需要谨慎,用一个能访问局部变量的函数去创建线程是危险的(除非十分确定线程会在函数完成前结束)

例子中使用了detach(),不等待线程结束。当oops()函数执行完成时,新线程中的函数可能还在运行。如果线程还在运行,它就会去调用do_something(i)函数,这时就会访问已经销毁的变量。如同一个单线程程序——允许在函数完成后继续持有局部变量的指针或引用。
解决:将数据复制到线程中(不使用引用),而非复制到共享数据中。
或者? ?可以通过join的方式来确保线程在函数完成 前结束。

线程等待

? ?如果需要等待线程, std::thread对象 实例需要使用join()。
例:把上面的 my_thread.detach() 替换为 my_thread.join() ,就可以确保局部变量在线程完成后,才被销 毁。

在C++的std::thread中,join()函数用于等待线程的完成,并清理与线程相关的资源。一旦调用了join()std::thread对象就不再与已经完成的线程有关联。这是因为一旦线程完成执行,它的资源(如线程栈等)就不再需要,而join()就是用来等待线程完成并释放这些资源的。

对于每个std::thread对象,只能调用一次join()。如果再次调用join(),就会导致运行时错误。

如果需要等待多个线程完成,可以创建一个线程数组或使用其他适当的数据结构,然后对每个线程调用join()

文章来源:https://blog.csdn.net/m0_52043808/article/details/135748952
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。