《C++ Concurrency in Action》读书笔记一 多线程与线程管理
2016-05-14 14:41
531 查看
简介,c++11 中STL标准加入了对多线程的支持。现在可以直接使用STL::thread来创建线程并且对线程进行管理
Cp1.通过一个hello world的例子引入C++11 中多线程的支持
Cp2.线程管理
1. 基本线程管理
1)std::thread的构造函数支持任何的std::function 比如函数,函数对象,lambda表达式等。作为std::thread的构造函数之参数。
2)线程启动以后可以选择join等待线程函数返回 或者deatch让其自动运行而不等待其返回。
join会等待线程执行结束而回收资源,detach调用之后会让线程成为守护线程资源回收交给runtime library管理
如果不执行join也不执行detach 会导致std::thread对象在退出栈的时候调用std::terminate()强制结束程序。
使用G++ 4.9.2 编译器执行的效果
3) 为了防止线程由于遇到exception而不能调用join来释放std::thread的资源,
可以使用try catch语句在catch中调用t.join在函数退出之前来等待线程结束。
使用类的析构函数来回收资源
使用RAII tr1::shared_ptr<std::thread> threadptr(thread_function, delete_function);
4)让线程在后台运行detach()
目标线程就成为了守护线程(daemon threads)驻留后台运行,与之关联的std::thread对象失去对目标线程的关联,无法再通过std::thread对象取得该线程的控制权。调用joinable()返回false。
2.传递参数给线程函数
1)参数默认是以拷贝方式传递给线程函数,就算线程函数的参数列表本身是引用方式,因为std::thread的构造函数默认并不知道线程函数的参数是引用。
这时候可以使用std::ref(parameter)强制以引用方式传递参数。
2)将对象的成员函数传递给std::thread的构造函数
这等效于调用了my_x.do_something()
3)传递只能move不可copy的参数例如std::unique_ptr
std::unique_ptr<int> p(10);
std::move(p);
3.传递std::thread的管理权
1)std::thread对象类似std::unique_ptr一样是不可copy但是可以move。
注意以下例子
2)std::thread可以作为函数的返回值 可以作为函数的参数传递
4.运行时选择创建线程的数量
1)创建复数的线程并等待他们结束
一个并行计算累积的例子
5. 标示线程
std::thread::id 使用get_it()函数
使用std::cout 输出id
std::cout<<std::this_thread::get_id();
Cp1.通过一个hello world的例子引入C++11 中多线程的支持
#include <iostream> #include <thread> void hello() { std::cout<<"Hello Concurrency World"<<std::endl; } int main() { std::thread t(hello); t.join(); return 0; }
Cp2.线程管理
1. 基本线程管理
1)std::thread的构造函数支持任何的std::function 比如函数,函数对象,lambda表达式等。作为std::thread的构造函数之参数。
2)线程启动以后可以选择join等待线程函数返回 或者deatch让其自动运行而不等待其返回。
join会等待线程执行结束而回收资源,detach调用之后会让线程成为守护线程资源回收交给runtime library管理
如果不执行join也不执行detach 会导致std::thread对象在退出栈的时候调用std::terminate()强制结束程序。
使用G++ 4.9.2 编译器执行的效果
3) 为了防止线程由于遇到exception而不能调用join来释放std::thread的资源,
可以使用try catch语句在catch中调用t.join在函数退出之前来等待线程结束。
使用类的析构函数来回收资源
#include <iostream> #include <thread> class thread_guard{ public: thread_guard(std::thread & t_):t(t_) { } ~thread_guard() { if(t.joinable()){ t.join(); std::cout<<"free the resource for the std::thread"<<std::endl; } } private: std::thread& t; }; void hello() { std::cout<<"Hello Concurrency World"<<std::endl; } int main() { std::thread t(hello); thread_guard g(t); //do something else. return 0; }
使用RAII tr1::shared_ptr<std::thread> threadptr(thread_function, delete_function);
#include <iostream> #include <thread> #include <tr1/memory> void hello() { std::cout<<"Hello Concurrency World"<<std::endl; } void release_thread(std::thread *t) { if(t->joinable()) { t->join(); std::cout<<"free the resource for the std::thread"<<std::endl; } } int main() { std::thread * t = new std::thread(hello); std::tr1::shared_ptr<std::thread> g(t, release_thread); //do something else. return 0; }
4)让线程在后台运行detach()
目标线程就成为了守护线程(daemon threads)驻留后台运行,与之关联的std::thread对象失去对目标线程的关联,无法再通过std::thread对象取得该线程的控制权。调用joinable()返回false。
2.传递参数给线程函数
1)参数默认是以拷贝方式传递给线程函数,就算线程函数的参数列表本身是引用方式,因为std::thread的构造函数默认并不知道线程函数的参数是引用。
这时候可以使用std::ref(parameter)强制以引用方式传递参数。
2)将对象的成员函数传递给std::thread的构造函数
class X{ public: void do_something(){}; }; X my_x; std::thread t(&X::do_something, &my_x)
这等效于调用了my_x.do_something()
3)传递只能move不可copy的参数例如std::unique_ptr
std::unique_ptr<int> p(10);
std::move(p);
3.传递std::thread的管理权
1)std::thread对象类似std::unique_ptr一样是不可copy但是可以move。
注意以下例子
std::thread t1(some_func1); std::thread t2(some_func2); t1 = std::move(t2); //这会导致程序强制结束std::terminate();
2)std::thread可以作为函数的返回值 可以作为函数的参数传递
std::thread f() { void some_function(); return std::thread(some_function); }
4.运行时选择创建线程的数量
1)创建复数的线程并等待他们结束
std::vector<std::thread> threads; for(unsigned i=0; i<20; ++i) { threads.push_back(std::thread(do_work)); } std::for_each(threads.begin(), threads.end(), std::mem_fn(&std::thread::join));2) std::thread::hardware_concurrency() 返回一个程序可以执行的最大线程数。在多核系统上通常是cpu的核心数。
一个并行计算累积的例子
template<typename Iterator, typename T> struct accumulate_block { void operator()(Iterator first, Iterator last, T& result) { result = std::accumulate(first, last, result); } }; template<typename Iterator, typename T> T parallel_accumulate(Iterator first, Iterator last, T init) { unsigned long const length = std::distance(first, last); if(!length) return init; unsigned long const min_per_thread = 25; unsigned long const max_thread = (length + min_per_thread - 1)/ min_per_thread; unsigned long const hardware_threads = std::thread::hardware_concurrency(); unsigned long const num_threads = std::min(hardware_threads!=0?hardware_threads:2, max_threads); unsigned long const block_size = length/num_threads; std::vector<T> results(num_threads); std::vector<std::thread> threads(num_threads-1); Iterator block_start = first; for(unsigned long i=0; i<(num_threads-1); ++i) { Iterator block_end = block_start; std::advance(block_end, block_size); threads[i] = std::thread( accumulate_block<Iterator, T>(), block_start, block_end, std::ref(results[i])); block_start = block_end; } accumulate_block<Iterator, T>()(block_start, last, results[num_threads-1]); std::for_each(threads.begin(), threads.end(), std::mem_fn(&std::thread::join)); return std::accumulate(results.begin(), results.end(), init); }
5. 标示线程
std::thread::id 使用get_it()函数
使用std::cout 输出id
std::cout<<std::this_thread::get_id();
相关文章推荐
- C++中通过指针来交换两个数
- 在OpenCV环境下写的两个图像平移C和C++源代码!
- 嵌入式C语言实例(达内2013)
- more effective c++ item26 控制对象的数量
- C++编译时多态之运算符重载
- C++中字节的长度
- ## c++学习笔记 --基础篇(第一周)##
- C++ 第二次课堂作业(反转链表)
- C++ 第二次课堂作业(反转链表)
- C/C++ 关于大小端模式
- C++实现“简单计算器”
- C语言_左移(<<)和右移(>>)
- c/c++ 参数传递 - 数组
- Oxford building dataset数据集计算正确相关图像ground truth的C++代码
- C++ 传递对象---用值传递对象
- 1.C++学习笔记:内存模型
- [容器]STL之set容器详解
- C++日记——浅谈继承
- C++名称空间
- c++文件的读取