C++并发实战3:向thread传递参数
来源:互联网 发布:董小飒淘宝赚多少钱 编辑:程序博客网 时间:2024/05/02 00:46
在创建thread object时可以向线程传递参数,默认情况下,参数会被拷贝到线程空间以供线程执行时存取,即使参数是引用也是这样。
情形1:
void f(int i,std::string const& s); boost::thread t(f,3,”hello”); //字符串常量“hello”会被转换为string,该string在线程中存在。
情形2:
void f(int i,std::string const& s);void oops(int some_param){ char buffer[1024]; sprintf(buffer, "%i",some_param); boost::thread t(f,3,buffer); //换成boost::thread t(f,3,string(buffer))保证安全 t.detach();}
这里会存在一个潜在的风险:当oops退出时,buffer会被销毁,但是如果此时在子线程中buffer还没有被转化成string,将会出现dangle pointer。一个解决办法是:boost::thread t(f,3,string(buffer));此时thread在构造时就会将buffer转换为string,并将string拷贝至子线程地址空间。
情形3:thread构造会拷贝其参数
#include<iostream>#include<string>#include<boost/thread.hpp>#include<unistd.h>using namespace std;class test{ public: test(int i=0):data(i){} test(const test& one){ data=one.data; cout<<"test::copy constructor"<<endl; } test& operator=(const test& one){ data=one.data; cout<<"test::operator=()"<<endl; return *this; } ~test(){ cout<<"test::destructor"<<endl; } public: int data;};void func(test& one){ cout<<"func get the data "<<one.data<<endl;}void oops(){ test one(10); boost::thread t(func,one); t.join();}int main(){ oops(); return 0;}
程序输出:
test::copy constructor
test::copy constructor
test::copy constructor
test::copy constructor
test::copy constructor
test::destructor
test::copy constructor
test::destructor
test::destructor
test::copy constructor
test::copy constructor
test::destructor
test::destructor
test::destructor
test::destructor
func get the data 10 //这里是线程函数的输出
test::destructor
test::destructor
说明:即使线程函数func采用引用方式,thread并不知道这一情形,所以在thread object在构造时会盲目的拷贝test one,然后thread将这个对象拷贝到线程地址空间作为internal copy,此后线程函数引用的是线程地址空间的那个internal copy,线程执行完毕,thread会销毁internal copy。对于这一点和boost::bind也一样,boost::bind也会拷贝参数。至于上面程序出现的那么多拷贝和析构输出已经我已无力解释了sorry。
情形4: 有些时候需要向线程传递一个引用,由线程执行一些计算最后这个计算结果将在主线程中使用,可以用boost::ref传递一个引用到线程空间。
#include<iostream>#include<string>#include<boost/thread.hpp>#include<boost/ref.hpp>#include<unistd.h>using namespace std;class test{ public: test(int i=0):data(i){} test(const test& one){ data=one.data; cout<<"test::copy constructor"<<endl; } test& operator=(const test& one){ data=one.data; cout<<"test::operator=()"<<endl; return *this; } ~test(){ cout<<"test::destructor"<<endl; } public: int data;};void func(test& one){ cout<<"func get the data "<<one.data++<<endl;}void oops(){ test one(10); boost::thread t(func,boost::ref(one)); t.join(); cout<<"oops() get the data "<<one.data<<endl;}int main(){ oops(); return 0;}
程序输出:
func get the data 10 //子线程修改数据
oops() get the data 11 //主线程将得到子线程修改后的结果,因为boost::ref是传递引用,没有拷贝构造之类的
test::destructor
情形5:thread传递函数对象
#include<iostream>#include<boost/thread.hpp>using namespace std;class test{ public: test(int i=0):data(i){} ~test(){ cout<<"test::destructor"<<endl; } test(const test& one){ data=one.data; } test& operator=(const test& one){ data=one.data; return *this; } void operator()(){ cout<<"test::operator() "<<data<<endl; } void show(){ cout<<"test::show() "<<data<<endl; } public: int data;};void oops(){ boost::thread t((test())); t.join();}int main(){ oops(); return 0;}程序输出:
test::destructor //函数对象没有产生copy constructor
test::destructor
test::destructor
test::operator() 0
test::destructor
情形6:仿照boost::bind将对象的成员函数作为线程函数
#include<iostream>#include<boost/thread.hpp>using namespace std;class test{ public: test(int i=0):data(i){} ~test(){ cout<<"test::destructor"<<endl; } test(const test& one){ data=one.data; } test& operator=(const test& one){ data=one.data; return *this; } void operator()(){ cout<<"test::operator() "<<data<<endl; } void show(){ cout<<"test::show() "<<data<<endl; } public: int data;};void oops(){ test one(10); boost::thread my_thread(&test::show,&one); my_thread.join();}int main(){ oops(); return 0;}
程序输出:
test::show() 10
test::destructor
说明:此时thread的线程将调用one::show(),thread将&one当做对象地址传递到线程中。
情形7:向thread传递指针:普通指针和智能指针。
#include<iostream>#include<boost/thread.hpp>#include<boost/shared_ptr.hpp>using namespace std;class test{ public: test(int i=0):data(i){} ~test(){ cout<<"test::destructor"<<endl; } test(const test& one){ data=one.data; } test& operator=(const test& one){ data=one.data; return *this; } public: int data;};void fun(boost::shared_ptr<test> ptr){ ptr->data++;}void fun_(test* ptr){ ptr->data++;}void oops(){ boost::shared_ptr<test> ptr(new test(10)); boost::thread my_thread(fun,ptr); my_thread.join(); cout<<"shared_ptr "<<ptr->data<<endl; test* one=new test(10); boost::thread t(fun_,one); t.join(); cout<<"test* "<<one->data<<endl; delete one;}int main(){ oops(); return 0;}
程序输出:
shared_ptr 11 //智能指针
test* 11 //普通指针
test::destructor
test::destructor
说明:传递指针给线程函数,thread拷贝的是指针对象,故线程对指针所指对象的修改将会影响到主线程中的对象。注意的是智能指针可能会引起对象生命周期的延长,若thread::detach那么智能指针肯定比普通裸指针安全,特别是detach后oops退出,智能指针管理的对象由于引用计数不会被析构,而普通裸指针由于oops退出析构了局部对象导致dangle pointer。
情形8:std::unique_ptr的movable语义传递参数
void process_big_object(std::unique_ptr<big_object>);std::unique_ptr<big_object> p(new big_object);p->prepare_data(42);std::thread t(process_big_object,std::move(p));//为什么一定要用std::move?std::unique_ptr是个左值对象,std::move的功能是将左值转为右值使用说明:std::unique_ptr不能共享所有权,但是可以转移所有权,采用std::move()语义后原来的std::unique_ptr将为NULL。
- C++并发实战3:向thread传递参数
- 向C语言程序传递命令行参数
- [C++11 并发编程] 03 - 向线程传递参数
- 向sqlplus传递参数
- 向脚本传递参数
- 向脚本传递参数
- 向报表传递参数
- 向Fragment传递参数
- 向脚本传递参数
- 向awk传递参数
- 向RDLC传递参数
- 向线程传递多个参数的变通方法(c#)
- C# Thread 传递多参数
- c# 多线程 Thread传递参数
- 实战 HTTP 处理程序(HTTP Handler) (2) -- 向HTTP 处理程序传递参数
- 向水晶报表传递参数
- 向水晶报表传递参数
- 如何向线程传递参数
- 修改xcode生成app的路径
- 300亿电商背后的IT架构美学与运维经验
- 【机器学习-斯坦福】学习笔记12 (EM算法)The EM Algorithm
- Linux shell用法和技巧
- ASP.NET MVC3 快速入门-第六节 增加一个追加数据的方法和一个追加数据的视图
- C++并发实战3:向thread传递参数
- Silverlight 跨线程访问无效
- linux网络报文接收发送浅析
- 函数模版template学习中的一个编译问题
- <A HREF="" target="_BLANK">打开的新窗口大小的控制 .
- java的基本数据类型小结
- 自己的总结!
- 谷歌——火狐浏览器及插件
- C#excel数据导入DataGridView第一行数据变成标题处理方法