boost muti-thread
背景
• 今天互联网应用服务程序普遍使用多线程来提高与多客户链接时的效率;为了达到最大的吞吐量,事务服务器在单独的线程上运行服务程序;
GUI应用程序将那些费时,复杂的处理以线程的形式单独运行,以此来保证用户界面能够及时响应用户的操作。这样使用多线程的例子还有很多。
• 跨平台
创建线程
• 头文件
namespace boost {
class thread;
class thread_group;
}
• thread():构造一个表示当前执行线程的线程对象
• explicit thread(const boost::function0& threadfunc)
注:boost::function0可以简单看为:一个无返回(返回void),无参数的函数。这里的函数也可以是类重载operator()构成的函数。
第一种方式:最简单方法
• #include
• #include
•
• void hello()
• {
• std::cout <<
• "Hello world, I''m a thread!"
• << std::endl;
• }
•
• int main(int argc, char* argv[])
• {
• boost::thread thrd(&hello);
• thrd.join();
• return 0;
• }
第二种方式:复杂类型对象作为参数来创建线程
• #include
• #include
• #include
•
• boost::mutex io_mutex;
•
• struct count
• {
• count(int id) : id(id) { }
•
• void operator()()
• {
• for (int i = 0; i < 10; ++i)
• {
• boost::mutex::scoped_lock
• lock(io_mutex);
• std::cout << id << ": "
• << i << std::endl;
• }
• }
•
• int id;
• };
•
• int main(int argc, char* argv[])
• {
• boost::thread thrd1(count(1));
• boost::thread thrd2(count(2));
• thrd1.join();
• thrd2.join();
• return 0;
• }
第三种方式:在类内部创建线程
• (1)类内部静态方法启动线程
• #include
• #include
• class HelloWorld
• {
• public:
• static void hello()
• {
• std::cout <<
• "Hello world, I''m a thread!"
• << std::endl;
• }
• static void start()
• {
•
• boost::thread thrd( hello );
• thrd.join();
• }
•
• };
• int main(int argc, char* argv[])
• {
• HelloWorld::start();
•
• return 0;
• }
• 在这里start()和hello()方法都必须是static方法。
• (2)如果要求start()和hello()方法不能是静态方法则采用下面的方法创建线程:
• #include
• #include
• #include
• class HelloWorld
• {
• public:
• void hello()
• {
• std::cout <<
• "Hello world, I''m a thread!"
• << std::endl;
• }
• void start()
• {
• boost::function0< void> f = boost::bind(&HelloWorld::hello,this);
• boost::thread thrd( f );
• thrd.join();
• }
•
• };
• int main(int argc, char* argv[])
• {
• HelloWorld hello;
• hello.start();
• return 0;
• }
• (3)在Singleton模式内部创建线程:
• #include
• #include
• #include
• class HelloWorld
• {
• public:
• void hello()
• {
• std::cout <<
• "Hello world, I''m a thread!"
• << std::endl;
• }
• static void start()
• {
• boost::thread thrd( boost::bind
• (&HelloWorld::hello,&HelloWorld::getInstance() ) ) ;
• thrd.join();
• }
• static HelloWorld& getInstance()
• {
• if ( !instance )
• instance = new HelloWorld;
• return *instance;
• }
• private:
• HelloWorld(){}
• static HelloWorld* instance;
•
• };
• HelloWorld* HelloWorld::instance = 0;
• int main(int argc, char* argv[])
• {
• HelloWorld::start();
• return 0;
• }
第四种方法:用类内部函数在类外部创建线程
• #include
• #include
• #include
• #include
• class HelloWorld
• {
• public:
• void hello(const std::string& str)
• {
• std::cout <
• }
• };
•
• int main(int argc, char* argv[])
• {
• HelloWorld obj;
• boost::thread thrd( boost::bind(&HelloWorld::hello,&obj,"Hello
• world, I''m a thread!" ) ) ;
• thrd.join();
• return 0;
• }
如果线程需要绑定的函数有参数则需要使用boost::bind。比如想使用 boost::thread创建一个线程来执行函数:void f(int i),
如果这样写:boost::thread thrd(f)是不对的,因为thread构造函数声明接受的是一个没有参数且返回类型为void的型别,而且
不提供参数i的值f也无法运行,这时就可以写:boost::thread thrd(boost::bind(f,1))。涉及到有参函数的绑定问题基本上都
是boost::thread、boost::function、boost::bind结合起来使用。
互斥体
• 一个互斥体一次只允许一个线程访问共享区。当一个线程想要访问共享区时,首先要做的就是锁住(lock)互斥体。
• Boost线程库支持两大类互斥体,包括简单互斥体(simple mutex)和递归互斥体(recursive mutex)。
有了递归互斥体,单个线程就可以对互斥体多次上锁,当然也必须解锁同样次数来保证其他线程可以对这个互斥体上锁。
• Boost线程库提供的互斥体类型:
boost::mutex,
boost::try_mutex,
boost::timed_mutex,
boost::recursive_mutex,
boost::recursive_try_mutex,
boost::recursive_timed_mutex,
boost::shared_mutex
• mutex类采用Scope Lock模式实现互斥体的上锁和解锁。即构造函数对互斥体加锁,析构函数对互斥体解锁。
• 对应现有的几个mutex导入了scoped_lock,scoped_try_lock,scoped_timed_lock.
• scoped系列的特色就是析构时解锁,默认构造时加锁,这就很好的确定在某个作用域下某线程独占某段代码。
mutex+scoped_lock
• #include
• #include
• #include
• #include
• boost::mutex io_mutex;
• void count(int id)
• {
• for (int i = 0; i < 10; ++i)
• {
• boost::mutex::scoped_lock lock(io_mutex);
• std::cout << id << ": " << i << std::endl;
• }
• }
• int main(int argc, char* argv[])
• {
• boost::thread thrd1(boost::bind(&count, 1));
• boost::thread thrd2(boost::bind(&count, 2));
• thrd1.join();
• thrd2.join();
• return 0;
• }
try_mutex+scoped_try_lock
• void loop(void)
• {
• bool running = true;
• while (running)
• {
• static boost::try_mutex iomutex;
• {
• boost::try_mutex::scoped_try_lock lock(iomutex);//锁定mutex
• if (lock.owns_lock())
• {
• std::cout << "Get lock." << std::endl;
• }
• else
• {
• // To do
• std::cout << "Not get lock." << std::endl;
• boost::thread::yield(); //释放控制权
• continue;
• }
• } //lock析构,iomutex解锁
• }
• }
timed_mutex+scoped_timed_mutex
• void loop(void)
• {
• bool running = true;
• while (running)
• {
• typedef boost::timed_mutex MUTEX;
• typedef MUTEX::scoped_timed_lock LOCK;
• static MUTEX iomutex;
• {
• boost::xtime xt;
• boost::xtime_get(&xt,boost::TIME_UTC);
• xt.sec += 1; //超时时间秒
• LOCK lock(iomutex, xt); //锁定mutex
• if (lock.owns_lock())
• {
• std::cout << "Get lock." << std::endl;
• }
• else
• {
• std::cout << "Not get lock." << std::endl;
• boost::thread::yield(); //释放控制权
• }
• //::sleep(10000); //长时间
• } //lock析构,iomutex解锁
• //::sleep(250);
• }
• }
shared_mutex
• 应用boost::thread的shared_mutex实现singled_write/multi_read的简单例子
• #include
• #include
• #include
• using namespace std;
• using namespace boost;
• boost::shared_mutex shr_mutex;
• /// 这个是辅助类,能够保证log_info被完整的输出
• class safe_log {
• public:
• static void log(const std::string& log_info) {
• boost::mutex::scoped_lock lock(log_mutex);
• cout << log_info << endl;
• }
• private:
• static boost::mutex log_mutex;
• };
• boost::mutex safe_log::log_mutex;
• void write_process() {
• shr_mutex.lock();
• safe_log::log("begin of write_process");
• safe_log::log("end of write_process");
• shr_mutex.unlock();
• }
• void read_process() {
• shr_mutex.lock_shared();
• safe_log::log("begin of read_process");
• safe_log::log("end of read_process");
• shr_mutex.unlock_shared();
• }
• int main() {
• thread_group threads;
• for (int i = 0; i < 10; ++ i) {
• threads.create_thread(&write_process);
• threads.create_thread(&read_process);
• }
• threads.join_all();
• ::system("PAUSE");
• return 0;
• }
条件变量
• 有的时候仅仅依靠锁住共享资源来使用它是不够的。有时候共享资源只有某些状态的时候才能够使用。
比方说,某个线程如果要从堆栈中读取数据,那么如果栈中没有数据就必须等待数据被压栈。这种情
况下的同步使用互斥体是不够的。另一种同步的方式--条件变量,就可以使用在这种情况下。
• boost::condition
typedef condition_variable_any condition;
void wait(unique_lock& m);
• boost::condition_variable
template
void wait(lock_type& m);
• #include
• #include
• #include
• #include
• const int BUF_SIZE = 10;
• const int ITERS = 100;
• boost::mutex io_mutex;
• class buffer
• {
• public:
• typedef boost::mutex::scoped_lock scoped_lock;
• buffer()
• : p(0), c(0), full(0)
• {
• }
• void put(int m)
• {
• scoped_lock lock(mutex);
• if (full == BUF_SIZE)
• {
• {
• boost::mutex::scoped_lock lock(io_mutex);
• std::cout << "Buffer is full. Waiting..." << std::endl;
• }
• while (full == BUF_SIZE)
• cond.wait(lock);
• }
• buf[p] = m;
• p = (p+1) % BUF_SIZE;
• ++full;
• cond.notify_one();
• }
• int get()
• {
• scoped_lock lk(mutex);
• if (full == 0)
• {
• {
• boost::mutex::scoped_lock lock(io_mutex);
• std::cout << "Buffer is empty. Waiting..." << std::endl;
• }
• while (full == 0)
• cond.wait(lk);
• }
• int i = buf[c];
• c = (c+1) % BUF_SIZE;
• --full;
• cond.notify_one();
• return i;
• }
• private:
• boost::mutex mutex;
• boost::condition cond;
• unsigned int p, c, full;
• int buf[BUF_SIZE];
• };
• buffer buf;
• void writer()
• {
• for (int n = 0; n < ITERS; ++n)
• {
• {
• boost::mutex::scoped_lock lock(io_mutex);
• std::cout << "sending: " << n << std::endl;
• }
• buf.put(n);
• }
• }
• void reader()
• {
• for (int x = 0; x < ITERS; ++x)
• {
• int n = buf.get();
• {
• boost::mutex::scoped_lock lock(io_mutex);
• std::cout << "received: " << n << std::endl;
• }
• }
• }
• int main(int argc, char* argv[])
• {
• boost::thread thrd1(&reader);
• boost::thread thrd2(&writer);
• thrd1.join();
• thrd2.join();
• return 0;
• }
线程局部存储
• 函数的不可重入。
• Boost线程库提供了智能指针boost::thread_specific_ptr来访问本地存储线程(thread local storage)。
• #include
• #include
• #include
• #include
• boost::mutex io_mutex;
• boost::thread_specific_ptr ptr;
• struct count
• {
• count(int id) : id(id) { }
• void operator()()
• {
• if (ptr.get() == 0)
• ptr.reset(new int(0));
• for (int i = 0; i < 10; ++i)
• {
• (*ptr)++; // 往自己的线程上加
• boost::mutex::scoped_lock lock(io_mutex);
• std::cout << id << ": " << *ptr << std::endl;
• }
• }
• int id;
• };
• int main(int argc, char* argv[])
• {
• boost::thread thrd1(count(1));
• boost::thread thrd2(count(2));
• thrd1.join();
• thrd2.join();
• return 0;
• }
仅运行一次的例程
• 如何使得初始化工作(比如说构造函数)也是线程安全的。
• “一次实现”(once routine)。“一次实现”在一个应用程序只能执行一次。
• Boost线程库提供了boost::call_once来支持“一次实现”,并且定义了一个标志boost::once_flag及一个初始化这个标志的宏 BOOST_ONCE_INIT。
• #include
• #include
• #include
• int i = 0;
• boost::once_flag flag = BOOST_ONCE_INIT;
• void init()
• {
• ++i;
• }
• void thread()
• {
• boost::call_once(&init, flag);
• }
• int main(int argc, char* argv[])
• {
• boost::thread thrd1(&thread);
• boost::thread thrd2(&thread);
• thrd1.join();
• thrd2.join();
• std::cout << i << std::endl;
• return 0;
• }
Boost线程库的未来
• Boost线程库正在计划加入一些新特性。其中包括boost::read_write_mutex,它可以让多个线程同时从共享区中读取数据,
但是一次只可能有一个线程向共享区写入数据;boost::thread_barrier,它使得一组线程处于等待状态,知道所有得线程
都都进入了屏障区;boost::thread_pool,他允许执行一些小的routine而不必每一都要创建或是销毁一个线程。
• Boost线程库已经作为标准中的类库技术报告中的附件提交给C++标准委员会,它的出现也为下一版C++标准吹响了第一声号角。
委员会成员对 Boost线程库的初稿给予了很高的评价,当然他们还会考虑其他的多线程库。他们对在C++标准中加入对多线程的
支持非常感兴趣。从这一点上也可以看出,多线程在C++中的前途一片光明。
boost muti-thread的更多相关文章
- boost:thread使用实例
/************************************************************************/ /*功能描述: boost thread使用实例 ...
- boost之thread
1.boost里的thread创建之后会立即启动. 代码示例: #include <iostream> #include <string> #include <vecto ...
- boost库thread.hpp编译警告honored已修复
请浏览:https://svn.boost.org/trac/boost/ticket/7874 #7874: compile warning: thread.hpp:342: warning: ty ...
- 关于boost的thread的mutex与lock的问题
妈的,看了好久的相关的知识,感觉终于自己有点明白了,我一定要记下来啊,相关的知识呀.... 1, 也可以看一下boost的线程指南:http://wenku.baidu.com/link?url=E_ ...
- 【boost】MFC dll中使用boost thread的问题
项目需要,在MFC dll中使用了boost thread(<boost/thread.hpp>),LoadLibraryEx的时候出现断言错误,去掉thread库引用后断言消失. 百度g ...
- Boost Thread学习笔记二
除了thread,boost种:boost::mutexboost::try_mutexboost::timed_mutexboost::recursive_mutexboost::recursive ...
- boost thread 在非正常退出时 内存泄露问题
在使用boost的thread库的时候,如果主程序退出,thread创建的线程不做任何处理,则会出现内存泄露. 解决方法: 在主线程退出时,对所有thread使用interrupt()命令,然后主程序 ...
- gcc boost版本冲突解决日记
问题背景 项目在Ubuntu10 64位 boost 1.55,boost采用的是项目内包含相对目录的形式部署 项目采用了 -Wall -Wextra -Werror -Wconversion 最高的 ...
- boost库(条件变量)
1相关理念 (1)类名 条件变量和互斥变量都是boost库中被封装的类. (2)条件变量 条件变量是thread库提供的一种等待线程同步的机制,可实现线程间的通信,它必须与互斥量配合使用,等待另一个线 ...
- Using Boost Libraries in Windows Store and Phone Applications
Using Boost Libraries in Windows Store and Phone Applications RATE THIS Steven Gates 18 Jul 2014 5:3 ...
随机推荐
- python编写telnet登陆出现TypeError:'str' does not support the buffer interface
python3支持byte类型,python2不支持.在python3中,telnet客户端向远程服务器发送的str要转化成byte,从服务器传过来的byte要转换成str,但是在python2不清楚 ...
- TCP/IP TIME_WAIT状态
百度运维部二面面试官问我这个 我直接懵逼了 TIME_WAIT状态是通信双方简历TCP连接后, 主动关闭的一方就会进入TIME_WAIT状态 1.client向server发送FIN(M),clien ...
- 看完final的感受
今天没课,(其实是有体育课的,去打了一会球就跑路了...)就在宿舍看world final ; 我去,老毛子真是好厉害,看的我目瞪口呆,哈喇子直流; 上交的大神好厉害,本来还以为上交要夺冠的,最后罚时 ...
- [wordpress]根据自定义字段排序并根据自定义字段查询
Wordpress中,根据根据自定义字段排序和查询是通过WP_Query()方法 如根据 一个自定义的sort的数字字段从小到大进行排序 $args = array( 'post_type' => ...
- 简洁的drag效果,自由拖拽div的实现及注意点
偶然间看到了以前做的一个简洁的div拖拽效果,修改了一下加点注释,经测试完美通过firefox/chrome/ie6-11,现拿来分享一下. 先说一下实现原理及要点,最主要的有三步.第一步是mouse ...
- C语言经典参考书籍
<C程序设计语言> Brian W.Kernighan,Dennis M.Ritchie 编著:C语言的开山之作.C程序员应该人手一本. <C语言参考手册> Samuel P. ...
- sql深入理解
我们做软件开发的,大部分人都离不开跟数据库打交道,特别是erp开发的,跟数据库打交道更是频繁,存储过程动不动就是上千行,如果数据量大,人员流动大,那么我们还能保证下一段时间系统还能流畅的运行吗?我们还 ...
- Swiper之滑块3
上章Swiper滑块2.Swiper滑块1都是手动的,这章我们来自动的! 其实只是加了Swiper的speed(滑动速度即slider自动滑动开始到结束的时间)属性而已(∩_∩),单位是ms < ...
- MySQL中DATE_FORMATE函数内置字符集解析
今天帮同事处理一个SQL(简化过后的)执行报错: 代码如下 复制代码 mysql> select date_format('2013-11-19','Y-m-d') > timediff( ...
- Python-Day15 JavaScript/DOM
JavaScript JavaScript是一门编程语言,浏览器内置了JavaScript语言的解释器,所以在浏览器上按照JavaScript语言的规则编写相应代码之,浏览器可以解释并做出相应的处理. ...