BOOST之Thread库学习

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/luguifang2011/article/details/41643511
//Boost并发编程之thread
/*-----------------------------------------------------编译thread库
在工程中嵌入源码的方式:
直接在cpp文件中包含thread库的实现代码如下
#define BOOST_DATE_TIME_SOURCE
#define BOOST_THREAD_NO_LIB
#inclue<boost\thread.hpp>
#ifdef _MSC_VER              //windows线程
extern "C" void tss_cleanup_implemented(void)()//一个必须的函数window下的thread库没有实现自动tss功能
#include<libs\thread\src\win32\thread.cpp>
#incldue<libs\thread\src\win32\tss_dll.cpp>
#include<libs\thread\src\win32\tss_pe_cpp>
#else
#include<lib\thread\src\pthread\thread.cpp>
#include<libs\thread\src\pthread\once.cpp>
#endif
-------------------------------------------------使用thread库
#define BOOST_DATE_TIME_SOURCE
#define BOOST_THREAD_NO_LIB
#include <boost\threaad.hpp>
--------------------------------------------时间功能
为了更好的表述时间线程的相关含义thread库重新定义新的时间类型system_time 他是posix::ptime同义词
thread库也提供一个自由函数get_system_time()它调用microse_clock类方便地获取当前utc时间
-------------------------------------------互斥量
Thread提供7中互斥量类型(实际上只有5中)
(1) Mutex:独占式的互斥量,最简单的一种互斥量类型
(2) Try_mutex:mutex同义为兼容以前版本
(3) Time_mutex:独占式,提供超时锁定功能
(4) Recursive_mutex:递归互斥量可以多次锁定
(5) Recursive_try_mutex:它是(4)的同义词为兼容
(6) Recursive_timed_mutex:他是递归式互斥量基本功能同(4)但提供超时锁定
(7) Share_mutex:multiple-reader/single-writer型的共享互斥锁(又称读写锁)
---------------------------------------互斥量的用法
直接使用mutex的成员函数来锁定互斥量不够方便而且在发生异常导致退出作用的情况下很可能忘记解除所覅那个;因此thread库提供一系列RAII型的lock_guard类由于辅助锁定互斥量。他们在构造时锁定互斥量在析构时自动解锁从而保证避免忘记解锁,就想一个智能指针
Mutex类使用内部类型定义的scoped_lock和scope_try_lock定义两种guard对象分别对应执行lock()和try_lock()
不适用guard对象:
Mutex mu;
Try{
Mu.lock()
Cout<<”some operation”<<endl;
Mu.unlock
}
Catch(….)
{
Mu.unlock();
}
使用lock_guard 类可以取消麻烦的try_catch块可以改为:
Mutex mu;
Mutex::scoped_lock lock(mu);
Cout<<”some operator”<<endl;
-----------------------------------------------------线程对象
thread类是thread库的核心对象
thread对象时不可拷贝的
thread通过特别的机制支持转移语义因此我们可以创建线程工程函数来封装threa创建细节返回一个thread对象
template<typename F>
thread_make(F f)
{
return thread(f);
}
---------------------------------------------------创建线程
thread 支持最多9个参数的传递且支持直接传递参数
---------------------------------------------------启动线程
当创建一个thread对象后线程立刻开始执行不提供类似start和begin那样用法
mutex io_mu
void printing(atom_int& x,const string& str)
{
for(int i=0;i<5;i++)
{
mutex::scoped_lock lock(io_mu)
cout<<str<<++x<<endl;
}
}
int main()
{
atom_int x;
thread(printing,ref(x),"hello");//传递多个参数
this_thread::sleep(posix_time::seconds(2));//等待2秒
}
----------------------------------------join和time_join
joinable()可以判断thread对象是否标示一个可执行的线程体如果joinable()返回true我们就可以调用join或者time_join来等待执行线程的结束
join()一直等待,time_join()等一时间段
----------------------------------------与线程执行体的分离
使用detach将thread与执行体手动分离此后thread对象不代表任何线程体,失去对线程的控制
thread t1(printing,ref(x),"hello");
t1.detach();
----------------------------------------bind和function的使用
bind库可以把函数所需的参数bind到一个函数对象上,而function则可以存储bind表达式的结果,供以后使用
thread t3(bind(printing),ref(x),"thread");
function<void()>f=bind(printing,5,"mutex");
thread(f);
----------------------------------------操作线程
get_id可以返回线程的id对象线程id提供了完整的比较操作符合流输出操作因此可以用标准容器管理


thread提供了三个静态成员函数
yield()  当前线程放弃时间片
sleep()让线程睡眠等待一段时间
hardware_concurrency()获取cpu数量或者cpu内核数量
-----------------------------------------中断线程
thread的成员函90数interrupt()允许正在执行的线程被中断被中断的线程会抛出thread_interrupted异常他是空类应该在线程执行函数里铺货并处理如果不处理那么就是终止线程


---------------------------------------线程中断点
thread 库预定义了若干个线程中断点,只有当线程执行到中断点的时候才能被中断,一个线程可以有任意多个中断点
预定义的9个中断点
thread::join();
thread::timed_join();
condition_variable::wait();
condition_variable::timed_wait();
condition/-cariable_any::wait();
condition/-cariable_any::timed_wait()
thread::sleep()
this_tread_sleep()
this_thread::interruption_point()
--------------------------------------------启用和禁用线程中断
interruption_enable()函数检测当前线程是否允许中断
interruption_requested()函数检测当前线程是否被要求中断
类disable_interruption 是RAII类型对象构造时关闭线程中断,析构时自动恢复中断,再其生命周期内始终是不可中断的除非使用了restore_interruption对象
restore_interruption对象只能在disable_interruption生命期内使用它在构造时临时打开线程中断状态析构时关闭中断状态
-------------------------------------------线程组
thread库提供类thread_group用于管理一组线程就像是线程池内部使用std::list<thread*>来容纳创建thread对象
create_thread()是一个工厂函数,可以创建thread对象并运行线程同时加入到内部的list中。
add_thread()提供加入线程组中
还有类似提供:
remove_thread()和join_all()interrupt_all()函数
thread_group tg;
tg.create_thread(bind(printing,ref(x),"C++"));
tg.create_thread(bind(printing,ref(x),"boost"));
------------------------------------------------------条件变量
thread库提供两种条件变量对象 condition_variable和condition_variable_any 一般情况下使用后一种
拥有条件变量的线程先锁定互斥量然后循环检查某个条件如果条件不满足那就调用条件变量的成员函数wait()等待直至条件满足,其他线程处理条件
变量要求的条件,当条件满足时调用它的成员函数notify_one()或notify_all(),通知所有正在等待条件的变量线程停止等待继续执行
------------------------------------------------用法
可以使用标准库的容器适配器queue介绍circular_buffer类来实现先进先出型和循环队列型缓冲区
class DataBuffer
#endif
{
public:
DataBuffer(size_t n) :unread(0), capacity(n){}
void put(const T& x);
void get(const T&x);

private:
mutex mu;
condition_variable_any cond_put;
condition_variable_any cond_get;
queue<T>stk;
int unread;
int capacity;
bool is_full()
{
return unread == capacity;
}
bool is_empty()
{
return unread == 0;
}


};
template<typename T>
DataBuffer<T>::DataBuffer()//初始情况下rnread=0;capacity=10;
{
unread = 0;
capacity = 10;
}
template<typename T>
void DataBuffer<T>::put(const T&x)
{
{
mutex::scoped_lock lock(mu);
while (is_empty())
{


{
/*缓冲区为空则等待*/
}
cond_get.wait(mu);
}
--unread;
*x = stk.front();
stk.pop();
}
cond_put.notify_one();
}
template<typename T>
void DataBuffer<T>::get(const T& x)
{
{
mutex::scoped_lock lock(mu);
while (is_full())
{
{
/*缓冲区满*/


}
cond_put.wait(mu);
}
stk.push(x);
++unread;


}
cond_get.notify_one();
}


template<typename T>
DataBuffer<T>::~DataBuffer()
{


}


-------------------------------------------------------------共享互斥变量
共享互斥量shared_mutex不同于mutex和recursive_mutex,它允许线程获取多个共享所有权和一个专享所有权实现了读写锁机制
如果要获取共享权的使用需调用lock_shared()或者try_lock_shared(),相应的使用unlock_shared来释放所有权
shared_mutex么有提供内部的lock_guard类型定义因此必须直接使用lock_guard对象
读锁定时使用shared_lock<shared_mutex>,写锁定时使用unique_lock<shared_mutex>
--------------------------------------------------使用




------------------------------------------future
thread库使用future范式提供一种异步操作线程返回值的方法因为这个返回值在线程开始执行时还是不可用的
packaged_task和promise两个模板类来包装异步调用,用unique_future和shared_future来获取异步调用结果
------------------packaged_task好像是一个reference_wrapper 或者function对象,它提供opertor()包装一个可回调物然后就可以被任意线程调用最后future值可以用成员函数get_future()获得
unique_future 用来存储packaged_task异步计算的future值,他只能持有唯一的一个引用
----------------------使用方法:
int fab(int n)//递归计算斐波那契数列
{


}


*/
#include<boost\thread.hpp>
#include<iostream>
using namespace std;
using namespace boost;
int fab(int n)//递归计算斐波那契数列
{
if (n == 0 || n == 1)
{
return 1;
}
return fab(n - 1) + fab(n - 2);
}
int main()
{
packaged_task<int>pt(bind(fab,30));//声明packaged_task对象用模板参数指明返回值的类型packaged_task只接受无参函数因此需要bind
unique_future<int> uf = pt.get_future();//声明unqiue_future对象接受packaged_task的future值 同样使用模板参数指明返回类型
thread(boost::move(pt));//启动线程计算必须使用boost::move()来转移pack_task对象因为packaged_task是不可拷贝的
uf.wait();//uf等待计算结果
assert(uf.is_ready() && uf.has_value());
cout << uf.get() << endl;
}
展开阅读全文

没有更多推荐了,返回首页