昨天在写作“大卫的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,或者Macintosh Carbon平台的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
中是一样的了。
转帖自:http://blog.youkuaiyun.com/billdavid/archive/2005/05/27/381914.aspx