昨天在写作“大卫的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://com.8s8s.com/it/it21796.htm