线程同步-信号量-strand的用法总结
作者:asio转载自:asio分享学习快乐更新时间:2009-8-2

这里展示不用boost::asio::strand而是利用常规线程同步的手段来完成线程的同步。
#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
class printer
{
public:
    printer(boost::asio::io_service& io):
       timer1_(io, boost::posix_time::seconds(1)),
       timer2_(io, boost::posix_time::seconds(1)),
       count_(0)
    {
       timer1_.async_wait(boost::bind(&printer::print1, this));
       timer2_.async_wait(boost::bind(&printer::print2, this));
    }
    ~printer()
    {
       std::cout << "Final count is " << count_ << "\n";
    }
    void print1()
    {
       mutex_.lock();
       if (count_ < 10)
       {
           std::cout <<"ThreadID:" <<GetCurrentThreadId() <<" Timer 1: " << count_ << "\n";
           ++count_;
           timer1_.expires_at(timer1_.expires_at() + boost::posix_time::seconds(1));
           timer1_.async_wait(boost::bind(&printer::print1, this));
       }
       mutex_.unlock();
    }
    void print2()
    {
       mutex_.lock();
       if (count_ < 10)
       {
           std::cout <<"ThreadID:" <<GetCurrentThreadId() <<" Timer 2: " << count_ << "\n";
           ++count_;
           timer2_.expires_at(timer2_.expires_at() + boost::posix_time::seconds(1));
           timer2_.async_wait(boost::bind(&printer::print2, this));
       }
       mutex_.unlock();
    }
private:
    boost::asio::deadline_timer timer1_;
    boost::asio::deadline_timer timer2_;
    int count_;
    boost::mutex mutex_;
};
int main()
{
    boost::asio::io_service io;
    printer p(io);
    boost::thread t(boost::bind(&boost::asio::io_service::run, &io));
    io.run();
    t.join();
    return 0;
}
 
这样的效果和原boost::asio的例5是差不多的,boost::asio除了支持原生的线程同步方式外还加入了新的asio::strand是有意义的,因为这两种方式还是有区别的。
1.     用mutex的方式阻塞的位置是已经进入printe函数以后,而strand是阻塞在函数调用之前的。
2.     相对来说,当大量的同样回调函数需要同步时,asio::strand的使用更为简单一些。
3.     用mutex的方式明显能够更加灵活,因为不仅可以让线程阻塞在函数的开始,也可以阻塞在中间,结尾。
4.     对于同步的对象来说,asio::strand就是对其支持的回调对象,mutex是对本身线程的一种同步。
 
基本上,两者是相辅相成的,各有用处,但是实际上,假如从通用性出发,从额外学习知识触发,个人感觉strand似乎是可有可无的,不知道有没有必须使用strand的情况。。。。
 
到此,asio文档中tutorial中的timer系列例子是结束了。其实这里展示的以asio基本原理为主,甚至都还没有接触到任何与网络相关的东西,但是,这些却是进一步学习的基础。。。。。。
 补充:利用strand实现的话:

#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

class printer
{
public:
  printer(boost::asio::io_service& io)
    : strand_(io),
      timer1_(io, boost::posix_time::seconds(1)),
      timer2_(io, boost::posix_time::seconds(1)),
      count_(0)
  {
    timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1, this)));
    timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2, this)));
  }

  ~printer()
  {
    std::cout << "Final count is " << count_ << "\n";
  }

  void print1()
  {
    if (count_ < 10)
    {
      std::cout << "Timer 1: " << count_ << "\n";
      ++count_;

      timer1_.expires_at(timer1_.expires_at() + boost::posix_time::seconds(1));
      timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1, this)));
    }
  }

  void print2()
  {
    if (count_ < 10)
    {
      std::cout << "Timer 2: " << count_ << "\n";
      ++count_;

      timer2_.expires_at(timer2_.expires_at() + boost::posix_time::seconds(1));
      timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2, this)));
    }
  }

private:
  boost::asio::strand strand_;
  boost::asio::deadline_timer timer1_;
  boost::asio::deadline_timer timer2_;
  int count_;
};

int main()
{
  boost::asio::io_service io;
  printer p(io);
  boost::thread t(boost::bind(&boost::asio::io_service::run, &io));
  io.run();
  t.join();

  return 0;
}