做boost :: asio异步写需要一个互斥量吗?

时间:2013-03-19 11:39:31

标签: c++ boost boost-asio

我正在尝试理解boost :: asio,但是它有一些问题。在this example如果我错了,请纠正我。

  1. 通过引用write()方法和do_write()的值给出消息。所以我认为这没关系,即使do_write是由io_service.post完成的,boost :: bind也是按值绑定消息。

  2. 但为什么 write_msgs _ 队列没有互斥锁,因为std :: deque可能会移动或复制其元素,如果需要,io_service :: run拥有它自己的线程,它不确保数据是否一致。

  3. 用指针做它不是更好。如果消息很长,则始终按值复制。但是使用new和delete,它们将在之前创建并在发送后删除。那我就像这样发送

  4. boost::asio::async_write(socket_,
          boost::asio::buffer(*write_msgs_.front().data(),
            write_msgs_.front().length()),
          boost::bind(&chat_client::handle_write, this,
            boost::asio::placeholders::error));
    

1 个答案:

答案 0 :(得分:4)

1)是否正确以及2)工作的原因。

这里不需要互斥锁,因为main和客户端处理程序线程之间的同步是通过io_service::post方法完成的。 post实际上并没有执行任何操作,只是向回调处理程序添加了一个回调(绑定方法),回调处理程序是执行io_service::run的线程,而这样的std :: deque只能由访问运行io_service::run的线程。

3)这是线程安全,异常安全和所有权的问题。

关于线程安全,您需要100%确定在调用write之后,只有一个线程将访问指针指向的字符串。
所有权和例外安全是这里更有趣的一点。如果你只想在你的双端队列中存储普通指针,你就会遇到异常安全问题,因为抛出异常会导致你的字符串不再被删除。为了避免这个问题,你需要像智能指针(例如:std :: unique_ptr)这样的东西,它需要C ++ 11移动语义或者一个shared_ptr,它会为引用计数增加额外的开销。最干净的解决方案是将C ++ 11移动语义与普通字符串结合使用。您可以将缓冲区移动到写入功能并进一步移动到处理程序中,并具有无复制和异常安全性的额外好处 在谈论性能和复制之前的另一点是,您应该测量这是否真的是一个问题,并且您不会遇到像网络I / O这样不同的东西。