为什么asyncio.Future与current.futures.Future不兼容? [英] Why is asyncio.Future incompatible with concurrent.futures.Future?

查看:125
本文介绍了为什么asyncio.Future与current.futures.Future不兼容?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这两个类代表了并发编程的出色抽象,因此令人不安的是它们不支持相同的API。

The two classes represent excellent abstractions for concurrent programming, so it's a bit disconcerting that they don't support the same API.

具体来说,根据文档


asyncio.Future concurrent.futures.Future 几乎兼容。

差异:


  • result() exception()不要接受超时参数,并且在将来尚未完成时引发异常。

  • add_done_callback()总是通过事件循环的 call_soon_threadsafe()来调用。

  • 此类与 current.futures 包中的> wait()和 as_completed()函数。

  • result() and exception() do not take a timeout argument and raise an exception when the future isn’t done yet.
  • Callbacks registered with add_done_callback() are always called via the event loop's call_soon_threadsafe().
  • This class is not compatible with the wait() and as_completed() functions in the concurrent.futures package.

上面的列表实际上是不完整的,有还有更多差异:

The above list is actually incomplete, there are a couple more differences:



  • running()方法

  • result() exception()可能会提高 InvalidStateError 如果调用得太早

  • running() method is absent
  • result() and exception() may raise InvalidStateError if called too early

由于事件循环使这些操作变得无用或难以执行?

Are any of these due to the inherent nature of an event loop that makes these operations either useless or too troublesome to implement?

add_done_callback()?无论哪种方式,都保证了在期货交易完成后的某个未指定时间发生回调,因此这两个类之间的回调是否完全一致?

And what is the meaning of the difference related to add_done_callback()? Either way, the callback is guaranteed to happen at some unspecified time after the futures is done, so isn't it perfectly consistent between the two classes?

推荐答案

差异的主要原因是线程(和进程)如何处理块与协程如何处理块的事件。在线程化过程中,当前线程将被挂起,直到任何情况解决并且线程可以继续前进为止。例如,在期货的情况下,如果您请求期货的结果,则可以暂停当前线程,直到该结果可用为止。

The core reason for the difference is in how threads (and processes) handle blocks vs how coroutines handle events that block. In threading, the current thread is suspended until whatever condition resolves and the thread can go forward. For example in the case of the futures, if you request the result of a future, it's fine to suspend the current thread until that result is available.

但是,事件循环的并发模型不是挂起代码,而是返回事件循环并在准备好时再次被调用。因此,请求尚未准备好结果的asyncio将来的结果是错误的。

However the concurrency model of an event loop is that rather than suspending code, you return to the event loop and get called again when ready. So it is an error to request the result of an asyncio future that doesn't have a result ready.

您可能会认为asyncio的未来可能只是等待而一会儿效率低下,协程封锁起来真的那么糟糕吗?事实证明,拥有协程封锁很可能意味着未来永远不会完成。将来的结果很有可能由与运行请求结果的代码的事件循环相关的某些代码设置。如果运行该事件循环的线程阻塞,则不会运行与该事件循环关联的代码。因此阻塞结果将导致死锁并阻止产生结果。

You might think that the asyncio future could just wait and while that would be inefficient, would it really be all that bad for your coroutine to block? It turns out though that having the coroutine block is very likely to mean that the future never completes. It is very likely that the future's result will be set by some code associated with the event loop running the code that requests the result. If the thread running that event loop blocks, no code associated with the event loop would run. So blocking on the result would deadlock and prevent the result from being produced.

因此,是的,接口的差异是由于这种固有的差异引起的。例如,您不希望将asyncio future与并发.futures服务员抽象一起使用,因为这又会阻塞事件循环线程。

So, yes, the differences in interface are due to this inherent difference. As an example, you wouldn't want to use an asyncio future with the concurrent.futures waiter abstraction because again that would block the event loop thread.

add_done_callbacks 的差异保证了回调将在事件循环中运行。这是所希望的,因为他们将获得事件循环的线程本地数据。而且,许多协程代码都假定它永远不会与来自同一事件循环的其他代码同时运行。也就是说,协程仅在来自同一事件循环的两个协程不在同一时间运行的假设下才是线程安全的。在事件循环中运行回调避免了很多线程安全问题,并使编写正确的代码更加容易。

The add_done_callbacks difference guarantees that callbacks will be run in the event loop. That's desirable because they will get the event loop's thread local data. Also, a lot of coroutine code assumes that it will never be run at the same time as other code from the same event loop. That is, coroutines are only thread safe under the assumption that two coroutines from the same event loop do not run at the same time. Running the callbacks in the event loop avoids a lot of thread safety issues and makes it easier to write correct code.

这篇关于为什么asyncio.Future与current.futures.Future不兼容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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