【问题标题】:do boost::asio async write need a mutex?boost::asio 异步写入是否需要互斥锁?
【发布时间】:2013-03-19 11:39:31
【问题描述】:

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

  1. 消息是通过引用 write() 方法和值给 do_write() 给出的。所以我觉得这样就ok了,虽然do_write是由io_service.post完成的,但是boost::bind是按值绑定消息的。

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

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

代码

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));

【问题讨论】:

    标签: c++ boost boost-asio


    【解决方案1】:

    1) 是正确的以及 2) 有效的原因。

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-22
      • 2010-09-12
      • 2011-12-01
      • 1970-01-01
      • 2011-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多