boost::thread简要分析(1):

boost::thread简要分析(1):thread
2007-05-18 21:04
昨天在写作“大卫的Design Patterns学习笔记”过程中,编写了一个多线程Producer -Consumer的示例,其中用到了boost ::thread,但在线程同步的问题上遇到了些问题,到csdn和vckbase上发帖子问了一下,也没人回答,没有办法,只好晚上回家搬出源码研究了一下,总算解决了问题,下面将自己的理解写下来,与大家分享、讨论。
注:以下讨论基于boost1 .32.0。

boost ::thread库跟boost ::function等很多其它boost组成库不同,它只是一个跨平台封装库(简单的说,就是根据不同的宏调用不同的API),里面没有太多的GP编程技巧,因此,研究起来比较简单。

boost ::thread库主要由以下部分组成:
thread
mutex
scoped_lock
condition
xtime
barrier
下面依次解析如下:

thread
thread自然是boost ::thread库的主角,但thread类的实现总体上是比较简单的,前面已经说过,thread只是一个跨平台的线程封装库,其中按照所使用的编译选项的不同,分别决定使用Windows线程API还是pthread,或者MAC的thread实现。以下只讨论Windows,即使用BOOST_HAS_WINTHREADS的情况。
thread类提供了两种构造函数:
thread ::thread ()
thread ::thread ( const function0 < void >& threadfunc )
第一种构造函数用于调用GetCurrentThread构造一个当前线程的thread对象,第二种则通过传入一个函数或者一个functor来创建一个新的线程。第二种情况下,thread类在其构造函数中间接调用CreateThread来创建线程,并将线程句柄保存到成员变量m_thread中,并执行传入的函数,或执行functor的 operator ()方法来启动工作线程。
此外,thread类有一个Windows下的程序员可能不大熟悉的成员函数join,线程(通常是主线程)可以通过调用join函数来等待另一线程(通常是工作线程)退出,join的实现也十分简单,是调用WaitForSingleObject来实现的:
WaitForSingleObject ( reinterpret_cast <HANDLE >(m_thread ), INFINITE );
我们可以用以下三种方式启动一个新线程:
1、传递一个工作函数来构造一个工作线程
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <iostream>

boost ::mutex io_mutex ;

void count ()      // worker function
{
     for ( int i = 0 ; i < 10 ; ++i )
     {

         boost ::mutex ::scoped_lock lock (io_mutex );
         std ::cout << i << std ::endl ;
     }
}


int main ( int argc , char * argv [])
{

     boost ::thread thrd1 (&count );
     boost ::thread thrd2 (&count );
     thrd1 .join ();
     thrd2 .join ();

     return 0 ;
}

2、传递一个functor对象来构造一个工作线程
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <iostream>

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 );          // lock io, will be explained soon.
             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 ;
}

3、无需将类设计成一个functor,借助bind来构造functor对象以创建工作线程
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>
#include <iostream>

boost ::mutex io_mutex ;

struct count
{

     static int num ;
     int id ;

     count () : id (num ++) {}

     int do_count ( int n )
     {

         for ( int i = 0 ; i < n ; ++i )
         {

             boost ::mutex ::scoped_lock lock (io_mutex );
             std ::cout << id << ": " << i << std ::endl ;
         }

         return id ;
     }
};


int count ::num = 1 ;

int main ( int argc , char * argv [])
{

     count c1 ;
     boost ::thread thrd1 (boost ::bind (&count ::do_count , &c1 , 10 ));
     thrd1 .join ();
     return 0 ;
}

其中bind是一个函数模板,它可以根据后面的实例化参数构造出一个functor来,上面的boost ::bind (&count ::do_count , &c1 , 10 )其实等价于返回了一个functor:
struct countFunctor
{

     int operator () ()
     {
         (&
c1 )->do_count ( 10 );      // just a hint, not actual code
     }
};

因此,以后就跟 2中是一样的了。

大卫注:后面还有两个部分:
1、线程同步
2、线程局部存储
原以为反正没有多少东西,写起来应该很快的,没想到真正写起来还蛮费事,后面两部分已基本写完,但有些地方还不能完全确定,为免分析有误贻笑大方,还是等两天再贴出来。

posted on 2005-05-19 15:14 大卫的思维空间 阅读(1176) 评论(3)  编辑 收藏

评论

 

路过~~~~~~
2005-05-19 21:42 |

# re: boost::thread有内存泄漏吗?

最近写程序时,程序中使用了boost的thread库,出现一个比较严重的内存泄漏问题,
开发及编译环境:win2000下用VC6.0+SP6,

在调试程序中用BoundsCheck查到boost的thread库中有比较多的内存泄漏.
不知老大有没碰到这种情况?
是否跟编译器有关,还是真的boost的thread库本身还不完善的缘故?

我是使用的boost_1.32_0版本的thread库.
其中只用了一个子线程来运行一个方法输出"hello world!".
代码如下:
#include<boost/thread/thread.hpp>
#include<iostream>

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;
}

就是这个例子,BoundsCheck就报出了不少的内存泄漏.
# re: boost::thread简要分析(1):thread dlutyuanhongl
 

你可能感兴趣的:(JOIN,thread,工作,struct,iostream,functor)