C++并发编程总结
文章目录
1.第二章小结
1.第二章小结
登录后复制
#include <iostream>
#include <thread> //①
#include <vector>
#include <algorithm>
void hello() // ②
{
std::cout << "Hello Concurrent World\n";
}
class background_task
{
public:
void do_something() const {}
void do_something_else() const {}
void operator()() const
{
do_something();
do_something_else();
}
};
struct func
{
int &i;
func(int &i_) : i(i_) {}
void operator()()
{
for (unsigned j = 0; j < 1000000; ++j)
{
std::cout << j; // 1. 潜在访问隐患:悬空引用
std::cout.flush();
}
}
};
void oops()
{
int some_local_state = 0;
func my_func(some_local_state);
std::thread my_thread(my_func);
my_thread.detach(); // 2. 不等待线程结束
} // 3. 新线程可能还在运行
// 解决线程生命周期的方法1
// void f()
// {
// int some_local_state = 0;
// func my_func(some_local_state);
// std::thread t(my_func);
// try
// {
// do_something_in_current_thread();
// }
// catch (...)
// {
// // 在异常处理过程中调用join(),从而避免生命周期的问题
// t.join(); // 1
// throw;
// }
// t.join(); // 2
// }
// 解决线程生命周期的方法2,使用RAII等待线程完成
// class thread_guard
// {
// std::thread &t;
// public:
// explicit thread_guard(std::thread &t_) : t(t_)
// {
// }
// ~thread_guard()
// {
// if (t.joinable()) // 1
// {
// t.join(); // 2
// }
// }
// thread_guard(thread_guard const &) = delete; // 3
// thread_guard &operator=(thread_guard const &) = delete;
// };
// struct func; // 定义在清单2.1中
// void f()
// {
// int some_local_state = 0;
// func my_func(some_local_state);
// std::thread t(my_func);
// thread_guard g(t);
// 即使do_something_in_current_thread抛出一个异常,这个销毁依旧会发生
// do_something_in_current_thread();
// } // 4
// std::thread和std::bind中若函数对象的参数带引用,需要注意的问题
using widget_data = std::int16_t;
using widget_id = std::int16_t;
void update_data_for_widget(widget_id w, widget_data &data) // 1
{
data = 10;
}
void oops_again(widget_id w)
{
widget_data data = 0;
// std::thread t(update_data_for_widget, w, data); // error:C++:std::thread arguments must be invocable after conversion to rvalues
// 这是因为thread本身的构造函数的参数:Args&&... __args造成的,
//虽然转发类型能提供引用,但是thread构造函数这里使用了std::decay,去掉了引用属性,所以需要自己增加引用属性,所以需要添加std::ref
std::thread t(update_data_for_widget, w, std::ref(data)); // 2,ok
t.join();
}
// std::thread支持移动,但不可拷贝
void test()
{
void some_function();
void some_other_function();
std::thread t1(some_function); // 1
std::thread t2 = std::move(t1); // 2
t1 = std::thread(some_other_function); // 3,为什么不显式调用std::move()转移所有权呢?因为,所有者是一个临时对象——移动操作将会隐式的调用。
std::thread t3; // 4
t3 = std::move(t2); // 5
t1 = std::move(t3); // 6 赋值操作将使程序崩溃,不能通过赋一个新值给std::thread对象的方式来”丢弃”一个线程
}
// 函数返回std::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;
}
// std::thread实例可作为参数进行传递
void f(std::thread t);
void g2()
{
void some_function();
f(std::thread(some_function));
std::thread t(some_function);
f(std::move(t));
}
// scoped_thread的用法
class scoped_thread
{
std::thread t;
public:
explicit scoped_thread(std::thread t_) : // 1
t(std::move(t_))
{
if (!t.joinable()) // 2
throw std::logic_error("No thread");
}
~scoped_thread()
{
t.join(); // 3
}
scoped_thread(scoped_thread const &) = delete;
scoped_thread &operator=(scoped_thread const &) = delete;
};
struct func; // 定义在清单2.1中
void f3()
{
int some_local_state;
scoped_thread t(std::thread(func(some_local_state))); // 4
do_something_in_current_thread();
} // 5
// 量产线程,等待它们结束
void do_work(unsigned id);
void f2()
{
std::vector<std::thread> threads;
for (unsigned i = 0; i < 20; ++i)
{
threads.push_back(std::thread(do_work, i)); // 产生线程
}
std::for_each(threads.begin(), threads.end(),
std::mem_fn(&std::thread::join)); // 对每个线程调用join()
}
// std::thread::id实例常用作检测线程是否需要进行一些操作
/*
主线程可能要做一些与其他线程不同的工作。这种情况下,启动其他线程前,它
可以将自己的线程ID通过std::this_thread::get_id()得到,并进行存储。就是算法核心部分(所有线程都一样的),每个线程都要检查一下,其拥有的线程ID是否与初始线程的ID相同。
*/
std::thread::id master_thread;
void some_core_part_of_algorithm()
{
if (std::this_thread::get_id() == master_thread)
{
do_master_thread_work();
}
do_common_work();
}
int main()
{
// 传递了一个临时变量
// std::thread t(background_task()); // error,C++编译器会将其解析为函数声明,而不是类型对象的定义。
// std::thread t((background_task())); // ok
std::thread t{background_task()}; // ok
// t.join(); // ④
// oops();
oops_again(1);
}