首页 / C++ / C++并发编程指南2
C++并发编程指南2
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了C++并发编程指南2,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5133字,纯文字阅读大概需要8分钟。
内容图文
![C++并发编程指南2](/upload/InfoBanner/zyjiaocheng/737/d801c296b0b943a0890847eb33381226.jpg)
文章目录
线程管理基础
每个程序至少有一个线程:执行main()函数的线程,其余线程有其各自的入口函数。线程与原始线程(以main()为入口函数的线程)同时运行。如同main()函数执行完会退出一样,当线程执行完入口函数后,线程也会退出。在为一个线程创建了一个 std::thread 对象后,需要等待这个线程结束;不过,线程需要先进行启动。
启动线程
C++线程启动可以归结为构造std::thread
对象:
void do_some_work();
std::thread my_thread(do_some_work);
其他构造std::thread
对象方法:
- 普通函数
- 列表初始化
- 仿函数:只要重载一个类的operator()方法
- lambda表达式
#include <iostream>
#include <thread>
using namespace std;
void hello()
{
cout << "hello concurrent world" << endl;
}
class background_task
{
public:
void operator()() const
{
cout << "class constructor" << endl;
}
};
int main()
{
thread t(hello); //启动一个新线程,执行hello
t.join();
thread t3{hello};
t3.join();
background_task bt;
thread t2(bt);
t2.join();
thread t4([] {
cout << "lambda" << endl;
});
t4.join();
return 0;
}
等待线程
join()
:确保局部变量在线程完成后,才被销毁。清理了线程相关的存储部分,这样 std::thread 对象将不再与已经完成的线程有任何关联。
通常,当倾向于在无异常的情况下使用join()时,需要在异常处理过程中调用join(),从而避免生命周期的问题。当然也可以使用RAII手法让线程退出时自动调用join()
detach
:分离一个线程。使用detach()会让线程在后台运行,这就意味着主线程不能与之产生直接交互。也就是说,不会等待这个线程结束;如果线程分离,那么就不可能有 std::thread 对象能引用它。通常称分离线程为守护线程(daemon threads),UNIX中守护线程是指,没有任何显式的用户接口,并在后台运行的线程。
向线程函数传递参数
注意:默认参数要拷贝到线程独立内存中,即使参数是引用的形式,也可以在新线程中进行访问。
- 在传递给std::thread构造函数之间就要将字面值转为对应的类型,以防止隐式转换失败。
void f(int i, string const & s)
{
cout << i << ":" << s << endl;
}
int main()
{
//1. 可能转换崩溃,导致线程出现未定义行为。
//thread t(f, 3, "hello");
//2. 使用std::string构造函数, OK
thread t(f, 3, std::string("hello"));
t.join();
return 0;
}
- 需要传递一个引用时。可以使用 std::ref 将参数转换成引用的形式
- 可以通过
std::bind
传递函数及参数给std::thread
构造函数。
class X
{
public:
void do_work(int i)
{
cout << i << endl;
}
};
int main()
{
X my_x;
int num(2);
std::thread t(&X::do_work, &my_x, num);
t.join();
return 0;
}
std::bind
提供的参数可以移动,但不能拷贝。"移动"是指:原始对象中的数据转移给另一对象,而转移的这些数据就不再在原始对象中保存了。- 当原对象是一个临时变量时,自动进行移动操作,但当原对象是一个命名变量,那么转移的时候就需要使用
std::move()
进行显示移动。 - 标准线程库中和
std::unique_ptr
在所属权上有相似语义类型的类有好几种,std::thread
为其中之一。 - 执行线程的所有权可以在多个 std::thread 实例中互相转移,这是依赖于 std::thread 实例的可移动且不可复制性。不可复制保性证了在同一时间点,一个 std::thread 实例只能关联一个执行线程;可移动性使得程序员可以自己决定,哪个实例拥有实际执行线程的所有权。
转移线程所有权
多个thread对象之间转移
- C++标准库中有很多资源占有(resource-owning)类型,比如 std::ifstream , std::unique_ptr 还有 std::thread 都是可移动,但不可拷贝。
- 执行线程的所有权可以在 std::thread 实例中移动,下面将展示一个例子。例子中,创建了两个执行线程,并且在 std::thread 实例之间(t1,t2和t3)转移所有权。
void some_function();
void some_other_function();
std::thread t1(some_function); // 1 新线程与t1关联
std::thread t2=std::move(t1); // 2 t1的所有权转到t2。执行some_function的线程与t2关联,t1不关联任何线程
t1=std::thread(some_other_function); // 3 临时thread对象创建线程并与t1关联
std::thread t3; // 4 t3默认构造函数创建,没有任何执行线程与t3关联
t3=std::move(t2); // 5 t2的所有权转到t3。
t1=std::move(t3); // 6 赋值操作将使程序崩溃。t1已经关联了一个线程,不能再次关联另外的线程。
函数返回thread对象
std::thread f()
{
void some_function();
return std::thread(some_function);
}
std::thread g()
{
void some_other_function(int);
std::thread t(some_other_function,42);
return t;
}
thread作为参数传递
void f(std::thread t);
void g()
{
void some_function();
f(std::thread(some_function));
std::thread t(some_function);
f(std::move(t));
}
多个线程并等待结束
#include <iostream>
#include <vector>
#include <thread>
#include <random>
#include <chrono>
using namespace std;
//产生随机数
default_random_engine e;
int randn(int start, int end)
{
uniform_int_distribution<int> u(start, end);
return u(e);
}
//让线程随机sleep 0-9s
void do_work(unsigned id)
{
cout << "id:" << id << " start..." << endl;
std::this_thread::sleep_for(std::chrono::seconds(randn(0, 9)));
cout << "id:" << id << " end"<< endl;
}
int main()
{
vector<thread> thds;
for (unsigned i = 0; i < 10; i++)
{
thds.push_back(thread(do_work, i ));
}
//等待所有线程结束
for_each(thds.begin(), thds.end(), mem_fn(&thread::join));
return 0;
}
运行时决定线程数量
返回硬件支持的线程数目:thread::hardware_concurrency()
。注意:可能返回0.
标识线程
类型为:std::thread::id
获取方式
- 通过
thread
对象的get_id()
直接获取 - 在当前线程中调用
this_thread::get_id()
std::thread::id 对象可以自由的拷贝和对比,因为标识符就可以复用。
- 如果两个对象的 std::thread::id 相等,那它们就是同一个线程,或者都“无线程”。
- 如果不等,那么就代表了两个不同线程,或者一个有线程,另一没有线程。
- 可以作为键值存储
内容总结
以上是互联网集市为您收集整理的C++并发编程指南2全部内容,希望文章能够帮你解决C++并发编程指南2所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。