第二章 线程管理

版权声明:本文为博主原创文章,转载时请注明来源。有问题请e-mail:[email protected] https://blog.csdn.net/u011177305/article/details/52227657

第2章中,我们将了解一下用于管理线程的类和函数

  

本章主要内容

  • 启动新线程
  • 等待线程与分离线程
  • 线程唯一标识符

  

使用C++线程库启动线程,可以归结为构造 std::thread 对象:

  

void do_some_work();

std::thread my_thread(do_some_work);

注意,当把函数对象传入到线程构造函数中时,需要避免"最令人头痛的语法解析"(C++'s most vexing parse, 中文简介)。如果你传递了一个临时变量,而不是一个命名的变量;C++编译器会将其解析为函数声明,而不是类型对象的定义。

  

例如:

扫描二维码关注公众号,回复: 3180203 查看本文章

std::thread my_thread(background_task());

  

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

  

解决方法:

使用在前面命名函数对象的方式,或使用多组括号①,或使用新一的初始化法②,可以避

免这个问题。

如下所示:

  • std::thread my_thread((background_task())); // 1
  • std::thread my_thread{background_task()}; // 2
  • 前面的不含()的
  • 使用lambda表达式也能避免这个问题。lambda表达式是C++11的一个新特性,它允许使用一个可以捕获局部变量的局部函数

    std::thread my_thread([]{

    do_something();

    do_something_else();

    });

      

  

  

2.1.2 等待线程完成

如果需要等待线程,相关的 std::tread 实例需要使用join()。清单2.1中,将 my_thread.detach() 替换为 my_thread.join() ,就可以确保局部变量在线程完成后,才被销毁。

  

join()是简单粗暴的等待线程完成或不等待。当你需要对等待中的线程有更灵活的控制时,比

如,看一下某个线程是否结束,或者只等待一段时间(超过时间就判定为超时)。想要做到这

些,你需要使用其他机制来完成,比如条件变量和期待(futures)

  

  

2.1.4 后台运行线程

  

清单2.4 使用分离线程去处理其他文档

void edit_document(std::string const& filename)

{

open_document_and_display_gui(filename);

while(!done_editing())

{

user_command cmd=get_user_input();

if(cmd.type==open_new_document)

{

std::string const new_name=get_filename_from_user();

std::thread t(edit_document,new_name); // 1

t.detach(); // 2

}

else

{

process_user_input(cmd);

}

}

}

如果用户选择打开一个新文档,为了让迅速打开文档,需要启动一个新线程去打开新文档①,

并分离线程②。与当前线程做出的操作一,新线程只不是打开另一个文件而已。所以,

edit_document函数可以复用,通过传参的形式打开新的文件。

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

  

十一

  

  

猜你喜欢

转载自blog.csdn.net/u011177305/article/details/52227657
今日推荐