1. 程式人生 > >【Boost】boost庫asio詳解2——strand與io_service區別

【Boost】boost庫asio詳解2——strand與io_service區別

[cpp] view plain copy  print?
  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.         staticint 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的執行結果:
[cpp] view plain copy  print?
  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的執行結果:
[cpp] view plain copy  print?
  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的佇列中加入任務.