ip :: tcp :: socket.close()线程安全吗? [英] Is ip::tcp::socket.close() thread safe?

查看:246
本文介绍了ip :: tcp :: socket.close()线程安全吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果套接字上有一个async_read,则应该有一个io_service的内部线程来检查套接字的状态.从另一个线程(也许当它正在运行io_service的单独处理程序时)调用socket.close()是否安全?

If there is a async_read on the socket ongoing, there should be a internal thread of io_service checking the status of the socket. Is it safe to call socket.close() from another thread (maybe when it is running a separate handler of the io_service)?

我的意思是,即使我可以保证我的处理程序也不会同时使用asio socket,它是否足够好(考虑到io_service的内部线程时)?

I mean even I can guarantee that my handlers will not use the asio socket concurrently, is it good enough (when taking the internal threads of io_service into consideration)?

更新: 我在大量的协程中使用async_read.与此文档底部的示例非常相似,不同之处是我的有一个额外的功能层,可以使用yield_context进行调用.如果在该示例中在my_strand中分派socket.close()操作,那么整个线程是否安全?换句话说,所有相关操作(async_read,中间async_read_some,堆栈式协程的隐式处理程序,socket.close())是否都将通过单链my_strand运行?

Update: I am using async_read in a stackful coroutine. Quite similar to the example at the bottom of this doc, except that mine has an extra layer of function calling with the yield_context. If I dispatch the socket.close() operation in my_strand in that example, is the whole thing thread safe? In another word, will all concerned operations (async_read, intermediate async_read_some, implicit handlers of the stackful coroutine, socket.close()) run through a single strand my_strand?

推荐答案

通常,并发调用同一套接字对象 1 是不安全的.组成的 async_read() 操作由零个或多个中间 async_read_some() 操作.这些中间操作仅在当前正在调用io_service::run()的线程中启动.内部线程是相当透明的,

In general, it is unsafe to make concurrent calls to the same socket object1. The async_read() composed operation is composed of zero or more intermediate async_read_some() operations. These intermediate operations are only initiated in threads that are currently calling io_service::run(). The internal threads are fairly transparent, and none of the threads listed in the Platform-Specific Implementation Notes will present a problem.

因此:

  • If a single thread is invoking io_service::run() and socket.close() is invoked from within a handler, then it is safe as there is no possibility of concurrent execution. The documentation refers to this as an implicit strand.
  • If a single thread is invoking io_service::run() and socket.close() is invoked from outside of a handler, then it is unsafe, as socket may have two concurrent calls: close() from outside of the io_service and async_read_some() from a thread that is currently calling io_service::run(). To make it thread safe, post a handler into the io_service that invokes socket.close().
  • If multiple threads are invoking io_service::run(), then an explicit strand is required to guarantee thread safety. The async_read() needs to be initiated from within a strand, and its completion handler must also be wrapped by the same strand. Furthermore, socket.close() should be dispatched through the strand.

对于堆栈式协同程序,请使用接受strandspawn() 重载将在strand的上下文中执行提供的功能.此外,当yield_context对象作为处理程序传递给异步操作时,这些处理程序(包括来自组合操作的中间处理程序)在strand的上下文中被调用.因此,为了确保线程安全,socket.close()必须为:

For stackful coroutines, using the spawn() overload that accepts a strand will execute the provided function within the context of the strand. Furthermore, when the yield_context object is passed as the handler to asynchronous operations, the handlers, including intermediate handlers from composed operations, are invoked within the context of the strand. Hence, to ensure thread safety, socket.close() must either be:

  • 在协程中调用:

  • invoked within the coroutine:

// The lambda will execute within the context of my_strand.
boost::asio::spawn(my_strand,
  [socket&](boost::asio::yield_context yield)
  {
    // In my_strand.
    // ...

    // The socket.async_read_some() operations that composed async_read()
    // will run within the context of my_strand.
    async_read(socket, ..., yield);

    // Still within my_strand.
    socket.close();
  });

  • 明确分配给<​​c9>:

  • explicitly dispatched on my_strand:

    // The lambda will execute within the context of my_strand.
    boost::asio::spawn(my_strand,
      [socket&](boost::asio::yield_context yield)
      {
        // In my_strand.
        // ...
    
        // The socket_.async_read_some() operations that composed async_read()
        // will run within the context of my_strand.
        async_read(socket, ..., yield);
      });
    
    my_strand.dispatch([socket&](){ socket.close(); });
    

  • 有关线程安全,组合操作和线程的更多详细信息,请考虑阅读答案.

    For more details on thread safety, composed operations, and strands, consider reading this answer.

    1. 修订历史记录此规则的异常情况.如果操作系统支持,则同步读取,写入,接受和连接操作是线程安全的.为了完整起见,我将其包括在此处,但建议谨慎使用.

    1. The revision history documents an anomaly to this rule. If supported by the OS, synchronous read, write, accept, and connection operations are thread safe. I an including it here for completeness, but suggest using it with caution.

    这篇关于ip :: tcp :: socket.close()线程安全吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆