浮萍晓生的开发日志

记录学习的旅程,把握可预见的未来

导航

线程同步-信号量-strand的用法总结

Posted on 2014-02-25 10:35  浮萍晓生  阅读(1625)  评论(0)    收藏  举报

这里展示不用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;
}