首页 / C++ / C++多线程编程(thread类)
C++多线程编程(thread类)
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了C++多线程编程(thread类),小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4788字,纯文字阅读大概需要7分钟。
内容图文
![C++多线程编程(thread类)](/upload/InfoBanner/zyjiaocheng/599/8c556a0040494a7a90abdb09aa81bbc4.jpg)
多线程库
C++11
中提供了多线程的标准库,提供了管理线程、保护共享数据、线程间同步操作、原子操作等类。
多线程库对应的头文件是#include <thread>
,类名为std::thread
。
串行程序:
#include <iostream> #include <thread> void function_1() { std::cout << "I'm function_1()" << std::endl; } int main() { function_1(); return 0; }
这是一个典型的单线程的单进程程序,任何程序都是一个进程,main()
函数就是其中的主线程,单个线程都是顺序执行。
将上面的程序改造成多线程程序,让function_1()
函数在另外的线程中执行:
#include <iostream> #include <thread> void function_1() { std::cout << "I'm function_1()" << std::endl; } int main() { std::thread t1(function_1); // do other things t1.join(); return 0; }
1. 构建一个std::thread类的
对象t1
,构造的时候传递了一个参数,这个参数是一个函数,这个函数就是这个线程的入口函数,函数执行完整个线程也就执行完了;
2. 线程创建成功后,就会立即启动;
3. 一旦线程开始运行, 就需要显式的决定是要等待它完成(join),或者分离它让它自行运行(detach)。需要在std::thread
对象被销毁之前做出决定;
本例选择了使用t1.join()
,主线程(main函数)会一直阻塞,直到子线程(function_1函数)完成,join()
函数的另一个任务是回收该线程中使用的资源;
我们也可以调用t1.detach()
,从而将子线程放在后台运行,所有权和控制权被转交给C++
运行时库,以确保与线程相关联的资源在线程退出后能被正确的回收。被分离的线程被称为守护线程(daemon threads)。线程被分离之后,即使该线程对象被析构了,线程还是能够在后台运行,只是由于对象被析构了,主线程不能够通过对象名与这个线程进行通信。线程对象(t1)和对象内部管理的线程(子线程)的生命周期并不一样;如果线程执行的快,可能内部的线程已经结束了,但是线程对象还活着;也有可能线程对象已经被析构了,内部的线程还在运行。
#include <iostream> #include <thread> void function_1() { //延时500ms 为了保证test()运行结束之后才打印 std::this_thread::sleep_for(std::chrono::milliseconds(500)); std::cout << "I'm function_1()" << std::endl; } void test() { std::thread t1(function_1); t1.detach(); // t1.join(); std::cout << "test() finished" << std::endl; } int main() { test(); //让主线程晚于子线程结束 std::this_thread::sleep_for(std::chrono::milliseconds(1000)); //延时1s return 0; } // 使用 t1.detach()时 // test() finished // I'm function_1() // 使用 t1.join()时 // I'm function_1() // test() finished
1. 由于线程入口函数内部有个500ms
的延时,所以在还没有打印的时候,test()
已经执行完成了,t1
已经被析构了,但是它负责的那个线程还是能够运行,这就是detach()
的作用;
2. 如果去掉main
函数中的1s
延时,会发现只打印了test() finished,因为主线程执行的太快,整个程序已经结束了,后台线程被C++
运行时库回收了;
3. 如果将t1.detach()
换成t1.join()
,test
函数会在t1
线程执行结束之后,才会执行结束。
一旦一个线程被分离了,就不能够再被join
了。如果非要调用,程序就会崩溃,可以使用joinable()
函数判断一个线程对象能否调用join()
void test()
{ std::thread t1(function_1); t1.detach(); if(t1.joinable()) t1.join(); assert(!t1.joinable()); }
线程类的构造函数
std::thread
类的构造函数是使用可变参数模板实现的,也就是说,可以传递任意个参数;第一个参数是线程的入口函数,而后面的若干个参数是该函数的参数。第一个参数是一个可调用对象(Callable Objects),可以是以下几种情况:
- 函数指针
- 重载了
operator()
运算符的类对象,即仿函数 lambda
表达式(匿名函数)std::function
// 普通函数 无参 void function_1() {} // 普通函数 1个参数 void function_2(int i) {} // 普通函数 2个参数 void function_3(int i, std::string m) {} std::thread t1(function_1); std::thread t2(function_2, 1); std::thread t3(function_3, 1, "hello"); t1.join(); t2.join(); t3.join();? 仿函数:
// 仿函数 class Fctor { public: void operator() () {} }; Fctor f; std::thread t4{Fctor()}; //注意加花括号一个仿函数类生成的对象,使用起来就像一个函数一样,比如上面的对象
f
,当使用f()
时就调用operator()
运算符。所以也可以让它成为线程类的第一个参数,如果这个仿函数有参数,同样的可以写在线程类的后几个参数上。
?
lambda表达式:
//[]捕获列表,用于捕获上下文变量供lambda使用 //同时,编译器根据该符号可以判断接下来是lambda函数 //()参数列表,无参数的话可以省略 //返回值类型 //{}函数体 std::thread t1( [](){std::cout << "hello" << std::endl;} ); //“world”为参数m的值 std::thread t2([](std::string m) {std::cout << "hello " << m << std::endl;}, "world");
std::function:
class A { public: void func1() {} void func2(int i) {} void func3(int i, int j) {} }; A a; //std::function<返回值类型(参数类型)> //std::bind(函数对象,参数) std::function<void(void)> f1 = std::bind(&A::func1, &a); std::function<void(void)> f2 = std::bind(&A::func2, &a, 1); std::function<void(int)> f3 = std::bind(&A::func2, &a, std::placeholders::_1); std::function<void(int)> f4 = std::bind(&A::func3, &a, 1, std::placeholders::_1); std::function<void(int, int)> f5 = std::bind(&A::func3, &a, std::placeholders::_1, std::placeholders::_2); std::thread t1(f1); std::thread t2(f2); std::thread t3(f3, 1); std::thread t4(f4, 1); std::thread t5(f5, 1, 2);? 原文链接1:https://www.jianshu.com/p/5d273e4e3cbb
原文链接2:https://www.jianshu.com/p/109df8a7e627
内容总结
以上是互联网集市为您收集整理的C++多线程编程(thread类)全部内容,希望文章能够帮你解决C++多线程编程(thread类)所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。