1. namespace
  2. {
  3. // strand提供串行执行, 能够保证线程安全, 同时被post或dispatch的方法, 不会被并发的执行.
  4. // io_service不能保证线程安全
  5. boost::asio::io_service m_service;
  6. boost::asio::strand m_strand(m_service);
  7. boost::mutex m_mutex;
  8. void print(int id)
  9. {
  10. // boost::mutex::scoped_lock lock(m_mutex);
  11. static int count = 0;
  12. PRINT_DEBUG("id: " << boost::lexical_cast<std::string>(id));
  13. PRINT_DEBUG("count: " << boost::lexical_cast<std::string>(++count));
  14. }
  15. void ioRun1()
  16. {
  17. while(true)
  18. {
  19. m_service.run();
  20. }
  21. }
  22. void ioRun2()
  23. {
  24. while(true)
  25. {
  26. m_service.run();
  27. }
  28. }
  29. void strand_print1()
  30. {
  31. // PRINT_DEBUG("Enter print1");
  32. m_strand.dispatch(boost::bind(print, 1));
  33. // PRINT_DEBUG("Exit print1");
  34. }
  35. void strand_print2()
  36. {
  37. // PRINT_DEBUG("Enter print2");
  38. m_strand.post(boost::bind(print, 2));
  39. // PRINT_DEBUG("Exit print2");
  40. }
  41. void strand_print3()
  42. {
  43. // PRINT_DEBUG("Enter print3");
  44. m_strand.post(boost::bind(print, 3));
  45. // PRINT_DEBUG("Exit print3");
  46. }
  47. void strand_print4()
  48. {
  49. // PRINT_DEBUG("Enter print4");
  50. m_strand.post(boost::bind(print, 4));
  51. // PRINT_DEBUG("Exit print4");
  52. }
  53. // 将上面的m_strand换成m_service后,
  54. void service_print1()
  55. {
  56. // PRINT_DEBUG("Enter print1");
  57. m_service.dispatch(boost::bind(print, 1));
  58. // PRINT_DEBUG("Exit print1");
  59. }
  60. void service_print2()
  61. {
  62. // PRINT_DEBUG("Enter print2");
  63. m_service.post(boost::bind(print, 2));
  64. // PRINT_DEBUG("Exit print2");
  65. }
  66. void service_print3()
  67. {
  68. // PRINT_DEBUG("Enter print3");
  69. m_service.post(boost::bind(print, 3));
  70. // PRINT_DEBUG("Exit print3");
  71. }
  72. void service_print4()
  73. {
  74. // PRINT_DEBUG("Enter print4");
  75. m_service.post(boost::bind(print, 4));
  76. // PRINT_DEBUG("Exit print4");
  77. }
  78. }
  79. void test_strand()
  80. {
  81. boost::thread ios1(ioRun1);
  82. boost::thread ios2(ioRun2);
  83. boost::thread t1(strand_print1);
  84. boost::thread t2(strand_print2);
  85. boost::thread t3(strand_print3);
  86. boost::thread t4(strand_print4);
  87. t1.join();
  88. t2.join();
  89. t3.join();
  90. t4.join();
  91. m_server.run();
  92. }
  93. void test_service()
  94. {
  95. boost::thread ios1(ioRun1);
  96. boost::thread ios2(ioRun2);
  97. boost::thread t1(service_print1);
  98. boost::thread t2(service_print2);
  99. boost::thread t3(service_print3);
  100. boost::thread t4(service_print4);
  101. t1.join();
  102. t2.join();
  103. t3.join();
  104. t4.join();
  105. m_service.run();
  106. }

test_strand的执行结果:

  1. 2013-01-05 17:25:34 626 [8228] DEBUG - id: 4
  2. 2013-01-05 17:25:34 631 [8228] DEBUG - count: 1
  3. 2013-01-05 17:25:34 634 [5692] DEBUG - id: 1
  4. 2013-01-05 17:25:34 637 [5692] DEBUG - count: 2
  5. 2013-01-05 17:25:34 640 [5692] DEBUG - id: 2
  6. 2013-01-05 17:25:34 642 [5692] DEBUG - count: 3
  7. 2013-01-05 17:25:34 646 [5692] DEBUG - id: 3
  8. 2013-01-05 17:25:34 649 [5692] DEBUG - count: 4

test_ioserivice的执行结果:

  1. 2013-01-05 17:26:28 071 [3236] DEBUG - id: 1
  2. 2013-01-05 17:26:28 071 [5768] DEBUG - id: 2
  3. 2013-01-05 17:26:28 071 [5108] DEBUG - id: 3
  4. 2013-01-05 17:26:28 076 [3236] DEBUG - count: 1
  5. 2013-01-05 17:26:28 079 [5768] DEBUG - count: 2
  6. 2013-01-05 17:26:28 083 [5108] DEBUG - count: 3
  7. 2013-01-05 17:26:28 087 [3236] DEBUG - id: 4
  8. 2013-01-05 17:26:28 099 [3236] DEBUG - count: 4

从结果可以看到, 在test_strand中print中两个打印函数成对执行, 在test_ioservice两个打印函数就没有线程安全可言了.
如果要保证test_ioservice同步, 就要加上mutex, 在代码中被注释的那句.

注意从日志的线程号中可知: 真正执行print()是主线程, ios1, ios2, 而t1, t2, t3, t4线程只是往ioservice的队列中加入任务.

asio 中strand的作用的更多相关文章

  1. (原创)拨开迷雾见月明-剖析asio中的proactor模式(二)

    在上一篇博文中我们提到异步请求是从上层开始,一层一层转发到最下面的服务层的对象win_iocp_socket_service,由它将请求转发到操作系统(调用windows api),操作系统处理完异步 ...

  2. (原创)拨开迷雾见月明-剖析asio中的proactor模式(一)

    使用asio之前要先对它的设计思想有所了解,了解设计思想将有助于我们理解和应用asio.asio是基于proactor模式的,asio的proactor模式隐藏于大量的细节当中,要找到它的踪迹,往往有 ...

  3. web.xml中load-on-startup的作用

    如下一段配置,熟悉DWR的再熟悉不过了:<servlet>   <servlet-name>dwr-invoker</servlet-name>   <ser ...

  4. C#中构造函数的作用

    C#中构造函数的作用 共同点: 都是实例化对象,初始化数据的 默认构造是说所有的类都从祖先object那继承了空参的构造方法,你不写与写空参构造都存在,而有参数的构造一般是自己写的,写就有不写就没有, ...

  5. MySQL数据库中delimiter的作用概述

    以下的文章主要是向大家描述的是MySQL数据库中delimiter的作用是什么?我们一般都认为这个命令和存储过程关系不大,到底是不是这样的呢?以下的文章将会给你相关的知识,望你会有所收获. 其实就是告 ...

  6. js中getBoundingClientRect的作用及兼容方案

    js中getBoundingClientRect的作用及兼容方案 1.getBoundingClientRect的作用 getBoundingClientRect用于获取某个html元素相对于视窗的位 ...

  7. Linq中关键字的作用及用法

    Linq中关键字的作用及用法 1.All:确定序列中的所有元素是否都满足条件.如果源序列中的每个元素都通过指定谓词中的测试,或者序列为空,则为 true:否则为 false. Demo: 此示例使用 ...

  8. JAVA中protected的作用

    JAVA中protected的作用   1.public:public表明该数据成员.成员函数是对所有用户开放的,所有用户都可以直接进行调用 2.private:private表示私有,私有的意思就是 ...

  9. url中#号的作用

    url中#号的作用就是本页面位置跳转 比如这个url地址:http://www.aaaaa.com/index.html?ad=34&m=c#red red就是index.html页面的依哥位 ...

随机推荐

  1. PS 基础知识 .atn文件如何使用

    ANT文件就是Frames.atn类动作文件 具体安装步骤如下 : (以CS4 为例) 启动Photoshop 点击"窗口" 选"动作" 在弹出的动作面板里,点 ...

  2. Mysql启动自己主动设置max_connections为其它值

    背景 有同学反应.产品连不上,登陆到server.发现连接数不够了. 接着先重新启动mysql,发如今mysql启动的时候会报Waring Warning Changed limits: max_op ...

  3. linux之return和exit引发的大问题(vfork和fork)

    在coolshell.cn上看到的一个问题.为此拿来研究一下. 首先 看看return和exit的差别 在linux上分别跑一下这个代码 int main() { return 0; //exit(0 ...

  4. spring 接收_header 作为get请求的httpheader

    今天项目遇到一个问题,我们项目用户验证和权限验证的信息(licence)是在http头中设置的,百度了一下,只有ajax才能设置头信息,form表单是无法设置的,但是我突然想起springMVC关于f ...

  5. bootstrap table api

    http://blog.csdn.net/rickiyeat/article/details/56483577

  6. OpenWrt:路由器上的Linux

    官网:https://openwrt.org/ 适于嵌入式设备的一个Linux发行版,可刷无线路由器. 相对原厂固件而言,OpenWrt不是一个单一.静态的固件,而是提供了一个可添加软件包的可写的文件 ...

  7. 使用Apache Commons Chain(转载)

    原博客出处:http://phil-xzh.iteye.com/blog/321536 使用Commons Chain 作为程序开发人员,我们经常需要对一个实际上程序性的系统应用面向对象的方法.商业分 ...

  8. Android-Bundle的说明和用法

    1.Bundle类的作用 Bundle类是一种数据载体,类似于Map,用于存放key-value名值对形式的值.相对于Map,它提供了各种常用类型的putXxx()/getXxx()方法, 如:put ...

  9. 前端基础——CSS盒子模型

    如今很多网页都是由很多个"盒子"拼接.嵌套而成,所以多少接触过网页设计的朋友一定都对CSS盒子模型有所了解. 为了更好的说明,先举个通俗的样例:在一个仓库中放了10个纸箱,每一个纸 ...

  10. error LNK1112: module machine type 'X86' conflicts with target machine type 'x64'

    1 这个error是什么原因造成的 cmake默认选择的是x86,即32位的生成子. 2 怎么解决这个error 在cmake ..的时候,在后面加上“-G "Visual Studio 1 ...