ACE 栅栏同步体介绍
本帖最后由 yunh 于 2014-3-3 13:59 编辑ACE 提供了一种特别的线程同步对象:ACE_Barrier,与其它的同步对象 Semaphore、Condition Variable、Mutex、Event、Readers/Writer Lock 不同,栅栏同步体在同步多个线程同时到达时更加有效,也更直观一些。下面是一个使用栅栏同步体的例子:
#include "stdafx.h"
#include "ace/Barrier.h"
#include "ace/Task_T.h"
#include "ace/OS_NS_unistd.h"
#define HAS_BARRIER
class HA_CommandHandler : public ACE_Task <ACE_MT_SYNCH>
{
public:
enum {
N_THREADS = 5
};
HA_CommandHandler (ACE_Barrier &startup_barrier,
ACE_Barrier &shutdown_barrier)
: startup_barrier_ (startup_barrier)
, shutdown_barrier_ (shutdown_barrier)
{
}
void init_handler ()
{
ACE_OS::srand (ACE_Thread::self ());
ACE_OS::sleep (ACE_Time_Value (0, ACE_OS::rand () % 1000000));
}
int handle_requests ()
{
for (int i=0; i<128; ++ i)
{
ACE_OS::sleep (ACE_Time_Value (0, ACE_OS::rand () % 100000));
ACE_DEBUG ((LM_DEBUG, "(%t: %T) working %u\n", i));
}
return -1;
}
virtual int svc ()
{
init_handler ();
#if defined (HAS_BARRIER)
startup_barrier_.wait ();
#endif
ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t: %D) started\n")));
while(handle_requests () > 0)
;
#if defined (HAS_BARRIER)
shutdown_barrier_.wait ();
#endif
ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%t: %D) ended\n")));
return 0;
}
private:
ACE_Barrier &startup_barrier_;
ACE_Barrier &shutdown_barrier_;
};
int ACE_TMAIN(int argc, ACE_TCHAR* argv[])
{
ACE_Barrier startup_barrier (HA_CommandHandler::N_THREADS);
ACE_Barrier shutdown_barrier (HA_CommandHandler::N_THREADS);
HA_CommandHandler handler (startup_barrier, shutdown_barrier);
handler.activate (THR_NEW_LWP | THR_JOINABLE, HA_CommandHandler::N_THREADS);
handler.wait ();
return 0;
}
这个例子是直接从《ACE Programmer's Guide》P238 摘过来的,ACE_Barrier 的用法相对简单,在构造器中输入要同步的线程数,例子中是5,在需要同步的集合点,调用 wait 即可,如果没有达到预期的线程数 (5),wait 会陷入等待,当最后一个线程调用了 wait 后,会释放之前所有等待的线程,包括它自身,此时这些线程将如同开闸放水一般,同时向下继续奔涌。使用了同步体后的输出如下:
(1380:11:32:20.434000) working 126
(3240:11:32:20.450000) working 127
(1172:11:32:20.450000) working 126
(1380:11:32:20.466000) working 127
(1172:11:32:20.481000) working 127
(1172: Mon Mar3 2014 11:32:20.481000) ended
(3240: Mon Mar3 2014 11:32:20.481000) ended
(1380: Mon Mar3 2014 11:32:20.481000) ended
(6916: Mon Mar3 2014 11:32:20.481000) ended
(3780: Mon Mar3 2014 11:32:20.481000) ended 可以看到,在结束时各个线程的输出时间基本一样,为了与不使用同步体的情况做对比,我在例子代码中加入了预编译条件 HAS_BARRIER,将其注释并重编译后,就可以看到不一样的情况:
(7888:11:34:19.946000) working 126
(4992:11:34:19.946000) working 121
(2808:11:34:19.962000) working 127
(7888:11:34:19.962000) working 127
(4992:11:34:19.962000) working 122
(2808: Mon Mar3 2014 11:34:19.962000) ended
(7888: Mon Mar3 2014 11:34:19.962000) ended
(8092:11:34:19.977000) working 122
(4992:11:34:19.993000) working 123
(8092:11:34:20.009000) working 123
(4992:11:34:20.024000) working 124
(8092:11:34:20.024000) working 124
(8092:11:34:20.024000) working 125
(8092:11:34:20.055000) working 126
(4992:11:34:20.055000) working 125
(4992:11:34:20.071000) working 126
(8092:11:34:20.087000) working 127
(8092: Mon Mar3 2014 11:34:20.087000) ended
(4992:11:34:20.102000) working 127
(4992: Mon Mar3 2014 11:34:20.102000) ended 各个线程的结束时间就参差不齐了,看来 ACE_Barrier 确实起作用了。
总结一下,Semaphore 适合于解决生产者/消费者问题,用来控制活动线程的个数,保证与当前可用资源相匹配;Readers/Writer Lock 适合于一种资源被多个线程访问,其中读取者数量明显多于写入者;Mutex 为二元信号量,适合于锁定临界区代码;Event 与 Condition Variable 则比较适合于线程间的某种条件得到满足的通知;Barrier 则适合于在某一个集合点同步关联线程。
好贴,加精
页:
[1]