【C++并发实战1】

boost::thread的使用

首先确定安装了boost


if(boost没安装)

{

return;

}


1    编写如下文件:

#include <iostream>
#include "boost\thread.hpp"
using namespace std;


void show()
{  
	cout<<"hello world "<<endl;  
}  
int main()
{  
	boost::thread t(show);		//这里还可以t(&show)也能成功, 和pthread_create一样  
	cout<<"main pid "<<" "<<t.get_id()<<endl;   
	if(!t.joinable())  
		cout<<"thread unjoinable"<<endl;  
	else
	{  
		cout<<"thread joinable"<<endl;  
		t.join(); 
	}  
	return 0;  
}  

程序输出:

main pid 1e00
thread joinable
hello world

(2、3行顺序不一定)


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

#include <iostream>
#include "boost\thread.hpp"
using namespace std;

class test
{  
public:  
	void operator()() const
	{  
		cout<<"operator() "<<*data<<endl;  
	}  
	test(int a=10)
	{  
		cout<<"constructor"<<endl;  
		data=new int(a);  
	}  
	int get() const
	{  
		return *data;  
	}  
	test(const test& one)
	{  
		cout<<"copy constructor"<<endl;  
		data=new int(one.get());	//深拷贝,否则段错误  [1]
	}  
private:  
	int* data;  
};  
int main()
{  
	test one;  
	boost::thread myThread(one);	//函数对象被拷贝进线程空间  
	myThread.join();  
	return 0;  
}  

程序输出:

constructor
copy constructor
copy constructor(为什么会有两次拷贝?是有一个临时对象做中转吗?)
operator() 10

前三行的输出是在主线程中输出的,最后一行是在新建线程中输出的


如果把[1]所在行data=new int(one.get());注释掉,程序输出:

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


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

#include <iostream>
#include "boost\thread.hpp"
using namespace std;

class test
{  
public:  
	void operator()() const{  
		cout<<"operator() "<<*data<<endl;  
	}  
	test(int a=10){  
		cout<<"constructor"<<endl;  
		data=new int(a);  
	}  
	int get() const{  
		return *data;  
	}  
	test(const test& one){  
		cout<<"copy constructor"<<endl;  
		data=new int(one.get());//深拷贝,否则段错误  
	}  
private:  
	int* data;  
};  
int main(){  
	//boost::thread myThread(test());	//错误,会被误以为一个无参数的函数指针并返回一个test对象,从而返回一个thread对象而不是启动线程  
	boost::thread myThread((test()));//多余的括号用于防止被解释为一个函数  
	//boost::thread myThread{test()};//书上这种用法,编译通不过  
	//也可以用函数对象test one(11);thread myThread(one);  
	myThread.join();  
	return 0;  
} 

输出结果:

constructor
copy constructor
copy constructor
operator() 10

前三行的输出是在主线程中输出的,最后一行是在新建线程中输出的


4thread结合boost::bind使用

#include <iostream>
#include "boost\thread.hpp"
#include "boost\bind.hpp"
using namespace std;

void show(int i)
{  
	cout<<"show() i="<<i<<endl;  
}  
int main()
{  
	boost::thread t(boost::bind(show, 100));  //或boost::thread t(boost::bind(&show, 100));
	t.join();  
	return 0;  
}  

程序输出:

show() i=100



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

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

#include <iostream>
#include "boost\thread.hpp"
#include <windows.h>
using namespace std;

void show(){  
	cout<<"thread show()"<<endl;  
}  
int main()
{  
	boost::thread t(show);  
	Sleep(1);  
	if(t.joinable())
	{  
		cout<<"joinable"<<endl;  
		t.join();  
	}  
	else
	{  
		cout<<"unjoinable"<<endl;  
	}  
	return 0;  
} 

程序输出:

thread show()
joinable


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

#include <iostream>
#include "boost\thread.hpp"
#include <Windows.h>
using namespace std;

void show()
{  
	Sleep(1);  
	cout<<"thread show"<<endl;  
}  
int main()
{  
	{  
		boost::thread t(show);  
		t.detach();  
	}  
	Sleep(10);  
	return 0;  
}

程序输出:
thread show



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

#include <iostream>
#include "boost\thread.hpp"
#include <windows.h>
using namespace std;

void fun()
{  
	for(int i=0;i<5;i++)
	{  
		cout<<"thread::fun()"<<endl;  
		Sleep(1);  
	}  
}  
int main()
{  
	{  
		boost::thread t(fun);  
	}  
	cout<<"main exit"<<endl;  
	Sleep(2);  
	return 0;  
} 

程序输出:

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


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

#include <iostream>
#include "boost\thread.hpp"
using namespace std;

void do_something(int& i){  
	i++;  
	cout<<i<<" ";  
}  
class func
{  
public:  
	func(int& i):i_(i){}  

	void operator()()
	{  
		for(int j=0;j<100;j++)  
			do_something(i_);  
	}  
public:  
	int &i_;  
};  

void oops()
{  
	int local=0;  
	func my_func(local);  
	boost::thread my_thread(my_func);  
	my_thread.detach();//分离线程  
	cout<<"oops() "<<local<<endl;//局部对象将会被销毁,do_something输出会出错  
}  

int main()
{  
	oops();  
	return 0;  
} 

程序输出:

oops() 0 //局部对象已经被销毁
1 2 3 4 5 6 1 //预想是输出1-100的数,最后一个“1”已经是错误数据了


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



[转自http://blog.csdn.net/liuxuejiang158blog/article/details/17025577, 有改动]


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值