Chinaunix首页 | 论坛 | 博客
  • 博客访问: 289964
  • 博文数量: 95
  • 博客积分: 618
  • 博客等级: 中士
  • 技术积分: 455
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-28 13:39
文章分类

全部博文(95)

文章存档

2015年(65)

2013年(1)

2012年(10)

2011年(19)

分类: C/C++

2015-06-28 11:19:00

boost::thread的使用

首先确定安装了boost,ubuntu采用:sudo apt-get install libboost-dev

再安装:sudo apt-get install libboost-thread-dev

1     编写如下文件:

点击(此处)折叠或打开

  1. #include<boost/thread.hpp>
  2. #include<unistd.h>
  3. #include<sys/syscall.h>
  4. #include<iostream>
  5. using namespace std;
  6. void show(){
  7.     cout<<"hello wolrd "<<syscall(SYS_gettid)<<endl;
  8. }
  9. int main(){
  10.     boost::thread t(show);//这里还可以t(&show)也能成功和pthread_create一样
  11.     cout<<"main pid "<<syscall(SYS_gettid)<<" "<<t.get_id()<<endl;
  12.     //t.detach();
  13.     if(!t.joinable())
  14.         cout<<"thread unjoinable"<<endl;
  15.     else{
  16.         cout<<"thread joinable"<<endl;
  17.         t.join();
  18.     }
  19.     return 0;
  20. }
注意编译的时候一定要带上-lboost_thread否则会报错:undefined reference to `boost::thread::join()'等,假设上面程序文件为test.cpp则编译为:g++ -o test test.cpp -lboost_thread

2     boost::thread可以接收一个函数对象作为参数 ,函数对象会被拷贝进线程空间,那么这里就要注意一个问题:拷贝语义,若必要请采用深拷贝

点击(此处)折叠或打开

  1. #include<boost/thread.hpp>
  2. #include<iostream>
  3. using namespace std;
  4. using namespace boost;
  5. class test{
  6.     public:
  7.         void operator()() const{
  8.             cout<<"operator() "<<*data<<endl;
  9.         }
  10.         test(int a=10){
  11.             cout<<"constructor"<<endl;
  12.             data=new int(a);
  13.         }
  14.         int get() const{
  15.             return *data;
  16.         }
  17.         test(const test& one){
  18.             cout<<"copy constructor"<<endl;
  19.             //data=new int(one.get());//深拷贝,否则段错误
  20.         }
  21.     private:
  22.         int* data;
  23. };
  24. int main(){
  25.     test one;
  26.     thread myThread(one);//函数对象被拷贝进线程空间
  27.     myThread.join();
  28.     return 0;
  29. }
程序输出:


constructor
copy constructor
copy constructor
copy constructor
copy constructor                    //为什么这么多拷贝????
段错误 (核心已转储)             //这里采用深拷贝可以消除段错误


3      可以向thread传递临时函数对象


点击(此处)折叠或打开

  1. #include<boost/thread.hpp>
  2. #include<iostream>
  3. using namespace std;
  4. using namespace boost;
  5. class test{
  6.     public:
  7.         void operator()() const{
  8.             cout<<"operator() "<<*data<<endl;
  9.         }
  10.         test(int a=10){
  11.             cout<<"constructor"<<endl;
  12.             data=new int(a);
  13.         }
  14.         int get() const{
  15.             return *data;
  16.         }
  17.         test(const test& one){
  18.             cout<<"copy constructor"<<endl;
  19.             data=new int(one.get());//深拷贝,否则段错误
  20.         }
  21.     private:
  22.         int* data;
  23. };
  24. int main(){
  25.     //thread mythread(test());//错误,会被误以为一个无参数的函数指针并返回一个test对象,从而返回一个thread对象而不是启动线程
  26.     thread myThread((test()));//多余的括号用于防止被解释为一个函数
  27.     //thread myThread{test()};//书上这种用法,编译通不过
  28.     //也可以用函数对象test one(11);thread myThread(one);
  29.     myThread.join();
  30.     return 0;
  31. }

  32. 程序输出:
  33. constructor
  34. copy constructor
  35. copy constructor
  36. copy constructor //少了一次拷贝,我已经无法解释了,求高人指教~
  37. operator() 10

  38. 4 thread结合boost::bind使用
  39. #include<iostream>
  40. #include<boost/thread.hpp>
  41. #include<boost/bind.hpp>
  42. using namespace std;
  43. void show(){
  44.     cout<<"show()"<<endl;
  45. }
  46. int main(){
  47.     boost::thread t(boost::bind(show));
  48.     t.join();
  49.     return 0;
  50. }
程序输出:


show()


5          thread还可以结合lambda表达式使用(lambda表达式不熟悉~待完善)


线程可能先于join完成,此时仍joinable

点击(此处)折叠或打开

  1. #include<iostream>
  2. #include<boost/thread/thread.hpp>
  3. #include<unistd.h>
  4. using namespace std;
  5. using namespace boost;
  6. void show(){
  7.     cout<<"thread show()"<<endl;
  8. }
  9. int main(){
  10.     thread t(show);
  11.     sleep(1);
  12.     if(t.joinable()){
  13.         cout<<"joinable"<<endl;
  14.         t.join();
  15.     }
  16.     else{
  17.         cout<<"unjoinable"<<endl;
  18.     }
  19.     return 0;
  20. }
程序输出:


thread show()
joinable


6          当detach线程后,线程生命周期可能长于thread对象


点击(此处)折叠或打开

  1. #include<iostream>
  2. #include<boost/thread/thread.hpp>
  3. #include<unistd.h>
  4. using namespace std;
  5. using namespace boost;
  6. void show(){
  7.     sleep(1);
  8.     cout<<"thread show"<<endl;
  9. }
  10. int main(){
  11.     {
  12.         thread t(show);
  13.         t.detach();
  14.     }
  15.     sleep(2);
  16.     return 0;
  17. }
程序输出:


thread show


7          当一个thread对象销毁前,必须显示的指定是join还是detach线程(必须保证join和detach的正确即使在异常抛出中。在thread对象销毁前作这个是join还是detach),否则一旦线程对象销毁后,thread析构函数对调用terminate()结束线程。如下:

点击(此处)折叠或打开

  1. #include<iostream>
  2. #include<unistd.h>
  3. #include<boost/thread.hpp>
  4. using namespace std;
  5. void fun(){
  6.     for(int i=0;i<5;i++){
  7.         cout<<"thread::fun()"<<endl;
  8.         sleep(1);
  9.     }
  10. }
  11. int main(){
  12.     {
  13.         boost::thread t(fun);
  14.     }
  15.     cout<<"main exit"<<endl;
  16.     sleep(2);
  17.     return 0;
  18. }

程序输出:


main exit
thread::fun()
thread::fun()                //子线程并没有输出5个thread::fun()说明被提前terminate了


8          如果不等待线程完成,一定要确保线程存取的对象是有效的比如:当线程函数持有一个局部变量的引用或指针时,但是这个局部变量缺被销毁了。


点击(此处)折叠或打开

  1. #include<iostream>
  2. #include<boost/thread.hpp>
  3. using namespace std;
  4. void do_something(int& i){
  5.     i++;
  6.     cout<<i<<" ";
  7. }
  8. class func{
  9.     public:
  10.         func(int& i):i_(i){}
  11.         void operator()(){
  12.             for(int j=0;j<100;j++)
  13.                 do_something(i_);
  14.         }
  15.     public:
  16.         int &i_;
  17. };
  18. void oops(){
  19.     int local=0;
  20.     func my_func(local);
  21.     boost::thread my_thread(my_func);
  22.     my_thread.detach();//分离线程
  23.     cout<<"oops() "<<local<<endl;//局部对象将会被销毁,do_something输出会出错
  24. }
  25. int main(){
  26.     oops();
  27.     return 0;
  28. }
程序输出:


oops() 0            //局部对象已经被销毁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29   //预想是输出1-100的数。


9      采用c++11重写演示上面程序:

点击(此处)折叠或打开

  1. #include<iostream>
  2. //#include<boost/thread.hpp>
  3. #include<thread>
  4. using namespace std;
  5. void do_something(int& i){
  6.     i++;
  7.     cout<<i<<" ";
  8. }
  9. class func{
  10.     public:
  11.         func(int& i):i_(i){}
  12.         void operator()(){
  13.             for(int j=0;j<100;j++)
  14.                 do_something(i_);
  15.         }
  16.     public:
  17.         int &i_;
  18. };
  19. void oops(){
  20.     int local=0;
  21.     func my_func(local);
  22.     thread my_thread(my_func);
  23.     my_thread.detach();
  24.     cout<<"oops() "<<local<<endl;
  25. }
  26. int main(){
  27.     oops();
  28.     return 0;
  29. }
假设文件保存为:test.cpp编译时:g++ -o test test.cpp -std=c++0x -lpthread,执行./test


oops() 01 2 3 4 5 6 7 8 9 10

   说明:子线程my_thread被分离后,oops()退出使局部对象my_func析构了(local也销毁了),此时子线程调用do_something()访问一个已经销毁的对象,从而错误。解决的办法是:子线程将数据拷贝到自己空间,从而替代共享数据的访问。这个问题类似于对象生命周期的管理,出现了析构竞态,也可以采用boost::shared_ptr管理对象的生命周期。


阅读(1789) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~