找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 7044|回复: 1

ACE 栅栏同步体介绍

[复制链接]
发表于 2014-3-3 13:54:14 | 显示全部楼层 |阅读模式
本帖最后由 yunh 于 2014-3-3 13:59 编辑

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

您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-12-22 10:44 , Processed in 0.025187 second(s), 6 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表